Android MVP 和 MVVM 使用场景

在 Android 开发中,MVP(Model-View-Presenter)和 MVVM(Model-View-ViewModel)是两种常见的架构模式。它们都旨在解决传统的 MVC(Model-View-Controller)模式中的问题,并提供更好的代码组织和测试的能力。本文将介绍这两种模式的使用场景,并提供相应的代码示例。

MVP(Model-View-Presenter)

MVP 架构模式主要用于解决界面逻辑和业务逻辑的分离问题。它将界面(View)和业务逻辑(Presenter)分开,通过一个中间层(Model)进行交互。这样可以简化界面的逻辑,提高代码的可维护性和可测试性。

在 MVP 中,View 负责展示数据和接收用户输入,Presenter 负责处理业务逻辑和与 Model 进行交互,Model 则负责数据的获取和处理。下面是一个使用 MVP 架构的登录示例:

// View 接口
public interface LoginView {
    void showLoading();
    void hideLoading();
    void showError(String message);
    void showSuccess();
}

// Presenter
public class LoginPresenter {
    private LoginView view;
    private UserRepository userRepository;

    public LoginPresenter(LoginView view, UserRepository userRepository) {
        this.view = view;
        this.userRepository = userRepository;
    }

    public void login(String username, String password) {
        view.showLoading();
        userRepository.login(username, password, new UserRepository.Callback() {
            @Override
            public void onSuccess() {
                view.hideLoading();
                view.showSuccess();
            }

            @Override
            public void onError(String message) {
                view.hideLoading();
                view.showError(message);
            }
        });
    }
}

// Model
public class UserRepository {
    public interface Callback {
        void onSuccess();
        void onError(String message);
    }

    public void login(String username, String password, Callback callback) {
        // 模拟登录请求
        if (username.equals("admin") && password.equals("123456")) {
            callback.onSuccess();
        } else {
            callback.onError("Invalid username or password");
        }
    }
}

在上面的示例中,View 接口定义了一系列展示界面的方法,Presenter 负责处理登录逻辑并通过回调方式通知 View。Model 是一个 UserRepository 类,负责模拟登录请求并返回结果。通过这种方式,界面逻辑和业务逻辑被有效地分离,每个部分的职责清晰明确。

MVVM(Model-View-ViewModel)

MVVM 是一种用于解决界面和数据绑定的架构模式。它将界面(View)和数据(Model)之间的关联交给了一个中间层(ViewModel)来处理。ViewModel 负责从 Model 中获取数据,并将其转换为界面可用的形式,同时也负责处理用户交互的逻辑。下面是一个使用 MVVM 架构的登录示例:

// View
public class LoginActivity extends AppCompatActivity {
    private LoginViewModel viewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        viewModel = ViewModelProviders.of(this).get(LoginViewModel.class);

        final EditText usernameEditText = findViewById(R.id.usernameEditText);
        final EditText passwordEditText = findViewById(R.id.passwordEditText);
        final Button loginButton = findViewById(R.id.loginButton);

        loginButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String username = usernameEditText.getText().toString();
                String password = passwordEditText.getText().toString();
                viewModel.login(username, password);
            }
        });

        viewModel.getLoginResult().observe(this, new Observer<LoginResult>() {
            @Override
            public void onChanged(LoginResult result) {
                if (result.isLoading()) {
                    showLoading();
                } else {
                    hideLoading();
                    if (result.isSuccess()) {
                        showSuccess();
                    } else {
                        showError(result.getError());
                    }
                }
            }
        });
    }

    private void showLoading() {
        // 显示加载中的 UI
    }

    private void hideLoading() {
        // 隐藏加载中的 UI
    }

    private void showError(String message) {
        // 显示错误提示
    }

    private void showSuccess() {
        // 显示登录成功提示
    }
}

// ViewModel
public class LoginViewModel extends ViewModel {
    private MutableLiveData<LoginResult> loginResult = new MutableLiveData<>();
    private UserRepository userRepository;

    public LoginViewModel() {
        userRepository = new UserRepository();
    }

    public LiveData<LoginResult> getLoginResult() {
        return loginResult;