也不知道从什么开始每一个安卓开发者肯定都能有意无意听到或者看到MVP,而且是愈演愈烈的姿态,那到底什么是MVP呢?
今天小编就来告诉读者朋友们,MVP到底有什么神奇的地方,是什么原因让那么多开发者青睐!!!
大家首先来看张图:
一个合格的程序狗一眼就能看出图下方正是我们最常见的MVC结构,而上面的图就是我们今天的主角MVP;
与MVC不同的是,MVP多了一个Presenter 并且只能通过Presenter单向操作View 和 Model,并且Presenter是通过接口操作View 和 Model。这样能最大量的降低代码耦合,利于后期程序的维护和迭代。
我们再来看一张图:
MVC:
MVP:
与传统MVC结构相比,MVP完全隔离了module 与 view 层,逻辑变得清晰。
好的 我们总结下MVP的优点:
1. 降低耦合
2. 层级职责更明显,逻辑清晰
3. 易于单元测试
当然 MVP也是有缺点的:
1. 造成类数量爆炸
2. 代码复杂度和学习成本高
3. 接口冗余
估计看完MVP的缺点很多人不大愿意使用这个结构了,但是好钻用在刀刃上。某些场景我们会乐于使用这些结构:
- 个人开发的小项目(怎么省劲怎么写MVC足够)
- 外包的模块功能(MVP 利于封装测试,代码阅读起来简单易懂,装逼利器)
- 十几人的大项目(不用MVC 不用MVP你试试!)
上实例:
实例部分写的很简单。当然逻辑看懂,什么大山都能new出来!!!
一个简单的登录实例:
Module: User.class
public class User {
private String userName;
private String passWord;
public User(String userName, String passWord) {
this.userName = userName;
this.passWord = passWord;
}
public User() {
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassWord() {
return passWord;
}
public void setPassWord(String passWord) {
this.passWord = passWord;
}
}
链接接口:LoginView.class
public interface LoginView {
public String getName();
public String getPsw();
public void clear();
public void login();
}
View:MainActivity.class
public class MainActivity extends AppCompatActivity implements LoginView, View.OnClickListener {
private EditText name;
private EditText psw;
private LoginPresenter presenter;
private Button login;
private Button clear;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
@Override
public String getName() {
return name.getText().toString();
}
@Override
public String getPsw() {
return psw.getText().toString();
}
@Override
public void clear() {
name.setText("");
psw.setText("");
}
@Override
public void login() {
presenter.login();
}
private void initView() {
name = (EditText) findViewById(R.id.name);
psw = (EditText) findViewById(R.id.psw);
presenter = new LoginPresenter(this, this);
login = (Button) findViewById(R.id.login);
login.setOnClickListener(this);
clear = (Button) findViewById(R.id.clear);
clear.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.login:
login();
break;
case R.id.clear:
clear();
break;
}
}
}
Presenter:
public class LoginPresenter {
private ProgressDialog dio;
private User user;
private LoginView loginView;
private Handler handler = new Handler();
public LoginPresenter(LoginView login, Activity act) {
this.user = new User();
this.loginView = login;
this.dio = new ProgressDialog(act);
}
public void login(){
if(equeal(loginView.getName())&&equeal(loginView.getPsw())){
showProgress();
Thread thread = new Thread(){
@Override
public void run() {
super.run();
try {
sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
hiddeProgress();
}
};
thread.start();
}
}
public boolean equeal(String str){
if(str!=null&&str!=""){
return true;
}
return false;
}
public void showProgress(){
dio.setProgressStyle(ProgressDialog.STYLE_SPINNER);
dio.setCancelable(true);
dio.setCanceledOnTouchOutside(false);
dio.setTitle("请稍后...");
handler.post(new Runnable() {
@Override
public void run() {
dio.show();
}
});
}
public void hiddeProgress(){
if(dio!=null&&dio.isShowing()){
handler.post(new Runnable() {
@Override
public void run() {
dio.hide();
}
});
}
}
注意:
在Presenter里面直接操作view会报错的,因为不在MainThread里面运行。请记得使用Handler,或者看我下面的RxBus模式。