Android MVP模式

来源:互联网 发布:java中scanner的作用 编辑:程序博客网 时间:2024/04/29 06:55

曾经在一个项目中有一个Activity是负责机票的创单,也就是生成订单的工作,这里的逻辑非常复杂。创单的参数就达到200多个,在创单之前还有许多数据校验以及重复订单的校验操作,如果全部在Activity中实现将会导致代码极其臃肿。
这里我们提供一种解决的思路,就是MVP模式,首先笼统的介绍一下MVP:
我们将Activity复杂的逻辑处理移至另外的一个类(Presenter)中时,Activity其实就是MVP模式中的View,它负责UI元素的初始化,建立UI元素与Presenter的关联(Listener之类),同时自己也会处理一些简单的逻辑(复杂的逻辑交由 Presenter处理)。
MVP的Presenter是框架的控制者,承担了大量的逻辑操作,而MVC的Controller更多时候承担一种转发的作用。因此在App中引入MVP的原因,是为了将此前在Activty中包含的大量逻辑操作放到控制层中,避免Activity的臃肿。
这种模式与MVC的区别:
(最主要区别)View与Model并不直接交互,而是通过与Presenter交互来与Model间接交互。而在MVC中View可以与Model直接交互
通常View与Presenter是一对一的,但复杂的View可能绑定多个Presenter来处理逻辑。而Controller是基于行为的,并且可以被多个View共享,Controller可以负责决定显示哪个View
Presenter与View的交互是通过接口来进行的,更有利于添加单元测试。
下面我们做一下设计:
我们用另一个例子来解释。

先来看包结构图

20140928093820322.png

建立Bean

public class UserBean {
private String mFirstName;
private String mLastName;
public UserBean(String firstName, String lastName) {
this. mFirstName = firstName;
this. mLastName = lastName;
}
public String getFirstName() {
return mFirstName;
}
public String getLastName() {
return mLastName;
}
}
建立Model

(处理业务逻辑,这里指数据读写),先写接口,后写实现

public interface IUserModel {
void setID(int id);

 void setFirstName(String firstName); void setLastName(String lastName); int getID(); UserBean load(int id);// 通过id读取user信息,返回一个UserBean

}
实现不在这里写了

Presenter控制器

建立presenter(主导器,通过iView和iModel接口操作model和view),activity可以把所有逻辑给presenter处理,这样java逻辑就从手机的activity中分离出来。

public class UserPresenter {
private IUserView mUserView;
private IUserModel mUserModel;

 public UserPresenter(IUserView view) {        mUserView = view;        mUserModel = new UserModel(); } public void saveUser( int id, String firstName, String lastName) {        mUserModel.setID(id);        mUserModel.setFirstName(firstName);        mUserModel.setLastName(lastName); } public void loadUser( int id) {       UserBean user = mUserModel.load(id);        mUserView.setFirstName(user.getFirstName()); // 通过调用IUserView的方法来更新显示        mUserView.setLastName(user.getLastName()); }

}
View视图

建立view(更新ui中的view状态),这里列出需要操作当前view的方法,也是接口

public interface IUserView {
int getID();

 String getFristName(); String getLastName(); void setFirstName(String firstName); void setLastName(String lastName);

}
activity中实现iview接口,在其中操作view,实例化一个presenter变量。

public class MainActivity extends Activity implements OnClickListener,IUserView {

 UserPresenter presenter; EditText id,first,last; @Override protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);       setContentView(R.layout. activity_main);       findViewById(R.id. save).setOnClickListener( this);       findViewById(R.id. load).setOnClickListener( this);        id = (EditText) findViewById(R.id. id);        first = (EditText) findViewById(R.id. first);        last = (EditText) findViewById(R.id. last);        presenter = new UserPresenter( this); } @Override public void onClick(View v) {        switch (v.getId()) {        case R.id. save:             presenter.saveUser(getID(), getFristName(), getLastName());             break;        case R.id. load:             presenter.loadUser(getID());             break;        default:             break;       } } @Override public int getID() {        return new Integer( id.getText().toString()); } @Override public String getFristName() {        return first.getText().toString(); } @Override public String getLastName() {        return last.getText().toString(); } @Override public void setFirstName(String firstName) {        first.setText(firstName); } @Override public void setLastName(String lastName) {        last.setText(lastName); }

}
因此,Activity及从MVC中的Controller中解放出来了,这会Activity主要做显示View的作用和用户交互。每个Activity可以根据自己显示View的不同实现View视图接口IUserView。

通过对比同一实例的MVC与MVP的代码,可以证实MVP模式的一些优点:

在MVP中,Activity的代码不臃肿;
在MVP中,Model(IUserModel的实现类)的改动不会影响Activity(View),两者也互不干涉,而在MVC中会;
在MVP中,IUserView这个接口可以实现方便地对Presenter的测试;
在MVP中,UserPresenter可以用于多个视图,但是在MVC中的Activity就不行。

0 0