Android开发MVP模式(初步认识)
首先先了解一下
- 什么是MVP?
- MVP和MVC到底有什么区别?
- 为什么使用MVP模式开发?
MVC ,M是指业务模型,V是指用户界面,C则是控制器,使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。比如一批统计数据可以分别用柱状图、饼图来表示。C存在的目的则是确保M和V的同步,一旦M改变,V应该同步更新。
把Controller和View混在一起,有什么问题?
1.难以测试。
必须手动点击,使用各种自动化的测试工具。
2.代码难以重用。
UI是很难重用,因为要求总是不同。所以,导致重复的代码四处 都是,维护麻烦。
MVP , Presenter完全把Model和View进行了分离,主要的程序逻辑在 Presenter里实现。而且,Presenter与具体的View是没有直接关联的,而是通过定义好的接口进行交互,从而使得在变更View时候可以 保持Presenter的不变,即重用!
MVP的优点:
1、模型与视图完全分离,我们可以修改视图而不影响模型
2、可以更高效地使用模型,因为所有的交互都发生在一个地方——Presenter内部
3、我们可以将一个Presenter用于多个视图,而不需要改变Presenter的逻辑。这个特性非常的有用,因为视图的变化总是比模型的变化频繁。
4、如果我们把逻辑放在Presenter中,那么我们就可以脱离用户接口来测试这些逻辑(单元测试)
详细看看mvp的具体实现demo
现在模拟登录需求:检查账号密码不能为空,账号密码都为“000”的时候才正确登录成功然后跳转页面,账号密码有误则Toast提示用户。
首先创建M层的接口ILoingModel
package com.zhongcg.mvpdemo.model;
import com.zhongcg.mvpdemo.model.listener.OnLoginListener;
public interface ILoginModel {
void login(String name, String pwd, OnLoginListener listener);
}
声明了一个login方法
然后看看ILoginModel的实现LoginModel
package com.zhongcg.mvpdemo.model.imp;
import com.zhongcg.mvpdemo.model.ILoginModel;
import com.zhongcg.mvpdemo.model.listener.OnLoginListener;
public class LoginModel implements ILoginModel {
@Override
public void login(String name, String pwd, OnLoginListener listener) {
if (name == null || name.toString().trim().equals("") || pwd == null || pwd.toString().trim().equals("")) {
listener.onUserInfoError();
}
// 网络请求,返回数据,并在这做解析操作
if(name.equals("000") && pwd.equals("000")){
listener.onSuccess();
}else{
listener.onLoinFail();
}
}
}
实现接口的Login方法,在这里登录,进行网络请求并解析数据。再回调OnLoginListener的方法。
然后看看V层的接口ILoginView
package com.zhongcg.mvpdemo.view;
public interface ILoginView {
String getUsername();
String getPwd();
void moveToMainAct();//登录成功跳转到相应的activity
void showToast(String msg);
}
在MVP模式里,View只应该有简单的Set/Get的方法,用户输入和设置界面显示的内容,除此就不应该有更多的内容,绝不容许直接访问Model–这就是与MVC很大的不同之处。
V的实现
package com.zhongcg.mvpdemo.act;
import com.zhongcg.mvpdemo.R;
import com.zhongcg.mvpdemo.presenter.LoginPresenter;
import com.zhongcg.mvpdemo.view.ILoginView;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity implements ILoginView, OnClickListener {
private EditText usernameEdt;
private EditText pwdEdt;
private Button loginBtn;
private LoginPresenter loginPresenter = new LoginPresenter();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loginPresenter.setView(this);
initView();
bindView();
}
private void bindView() {
loginBtn.setOnClickListener(this);
}
private void initView() {
usernameEdt = (EditText) findViewById(R.id.username_edt);
pwdEdt = (EditText) findViewById(R.id.pwd_edt);
loginBtn = (Button) findViewById(R.id.loginBtn);
}
@Override
public String getUsername() {
return usernameEdt.getText().toString();
}
@Override
public String getPwd() {
return pwdEdt.getText().toString();
}
@Override
public void moveToMainAct() {
// 登陆成功
Toast.makeText(getApplicationContext(), "登陆成功", Toast.LENGTH_SHORT).show();
}
@Override
public void showToast(String msg) {
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.loginBtn:
loginPresenter.login();
break;
default:
break;
}
}
}
最后我们来看看P层是如何控制他们的逻辑的:
package com.zhongcg.mvpdemo.presenter;
import com.zhongcg.mvpdemo.model.ILoginModel;
import com.zhongcg.mvpdemo.model.imp.LoginModel;
import com.zhongcg.mvpdemo.model.listener.OnLoginListener;
import com.zhongcg.mvpdemo.view.ILoginView;
public class LoginPresenter implements OnLoginListener {
private ILoginModel loginModel;
private ILoginView loginView;
public LoginPresenter() {
this(new LoginModel());
}
public LoginPresenter(ILoginModel loginModelImp) {
this.loginModel = loginModelImp;
}
public void setView(ILoginView loginView) {
this.loginView = loginView;
}
public void login() {
String username = loginView.getUsername();
String pwd = loginView.getPwd();
loginModel.login(username, pwd, this);
}
@Override
public void onSuccess() {
loginView.moveToMainAct();
}
@Override
public void onUserInfoError() {
loginView.showToast("请检查用户账号密码格式");
}
@Override
public void onLoinFail() {
loginView.showToast("账号密码有误,请重新输入");
}
}
个人总结:P层就是用来做业务逻辑处理的,要是遇到需求逻辑改动,那么直接改P层。Adapter适配器写的位置,因为adapter会根据不同的model来展示不同的效果,自身不需要进行修改操作,所以归到P层实现比较合适。