MVP模式在android中现在已经非常火,相信下面的步骤会为你带来更清晰的编写方式,提高对MVP的理解。
首先为了便于理解,我们先看一下界面:
我们要实现的功能为:
- 点击save按钮:把first name和last name存储到数据库内,并绑定到edittext内填写的id上;
- 点击load按钮:根据edittext内id的值读取数据库中的内容并把数据展示到相应的edittext中。
所以不管是save还是load,edittext_id内必须有值。
具体步骤如下:
1.创建view层的的接口IUserView ,接口内定义跟view内展示的内容有关的相关方法,并让activity实现IUserView ;
ex:
public interface IUserView {
//获取view层activity中edittext中的内容
//由于不管save还是load,edittext_id里的内容都是我们手动输入进去的,所以不需要setID()方法
int getID();
String getFristName();
String getLastName();
//向view层activity中edittext中设置内容
void setFirstName(String firstName);
void setLastName(String lastName);
}
2.创建presenter层的类UserPresenter作为连接view层和model层的通道,并创建两个对象:
- IUserView 对象,通过构造方法传进,用于把model层的数据显示到实现IView接口的类中(即activity);
- IUserModel对象,在构造方法内创建(假如有实现类的话可以通过父类引用指向子类对象的方式创建),用于把view层展示的内容传到model层中,并在实现类中具体实现(如保存、计算、传到服务器等等)。
presenter的代码大概如下 ex:
public class UserPresenter{
private IUserView mUserView;
private IUserModel mUserModel;
public UserPresenter(IUserView view) {
mUserView = view;
mUserModel = new UserModel();//父类引用指向子类对象
}
/**把view层的数据保存到model中(由于是父类引用指向子类对象,所以具体的保存操作可以在UserModel中实现)*/
public void saveUser(int id, String firstName, String lastName) {
mUserModel.setID(id);
mUserModel.setFirstName(firstName);
mUserModel.setLastName(lastName);
}
/**把model层中的数据展示到view层*/
public void loadUser(int id) {
UserBean user = mUserModel.load(id);
mUserView.setFirstName(user.getFirstName());// 通过调用IUserView的方法来更新显示
mUserView.setLastName(user.getLastName());
}
}
当然也可以抽象出一个IUserPresenter接口,让UserPresenter实现接口并重写接口中的方法:
//Presenter的接口
public interface IUserPresenter{ //5
void saveUser(int id, String firstName, String lastName);
void loadUser(int id) ;
}
public UserPresenter extend IUserPresenter{
...
}
3、在activity中创建presenter对象,用于连接view层与presenter层(继而连接model层),并在相应的触发事件中调用presenter对象中的方法,完成传输。
ex:
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);//创建presenter对象
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.save:
if(id.getText().toString().equals("")){
Toast.makeText(MainActivity.this, "id is not be null", Toast.LENGTH_SHORT).show();
return;
}
presenter.saveUser(getID(), getFristName(), getLastName());//调用保存方法
break;
case R.id.load:
if(id.getText().toString().equals("")){
Toast.makeText(MainActivity.this, "id is not be null", Toast.LENGTH_SHORT).show();
return;
}
presenter.loadUser(getID());//调用展示方法
break;
default:
break;
}
}
//以下内容为实现IUserView接口中的方法
@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);
}
}
4、编写model层中的接口IUserModel,并定义存储数据的方法和读取数据的方法(具体调用已在第二步presenter的方法中写出),ex:
public interface IUserModel {
//存储数据的三个方法:
void setID(int id);
void setFirstName(String firstName);
void setLastName(String lastName);
//读取数据的方法:
UserBean load(int id);// 通过id读取user信息,返回一个UserBean
}
5、编写接口IUserModel的实现类(Impl) UserModel,可具体实现存储到数据库或从数据库中读取等操作,ex:
public class UserModel implements IUserModel {
@Override
public void setID(int id) {
// 存储id到数据库
}
@Override
public void setFirstName(String firstName) {
// 存储firstName到数据库
}
@Override
public void setLastName(String lastName) {
// 存储lastName到数据库
}
@Override
public UserBean load(int id) {
// 查数据库或者联网获取id的userbean
return new UserBean("11", "22");
}
}
6、实体类,这一个放到最后一步显然不太合适,但为了可以只把关注点放在view层、presenter层和model层,这里把它剥离出来放到最后写出,ex:
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;
}
}
至此,整个mvp模式的简单应用就结束了,可能好多朋友会觉得相比只把这些很简单的功能放在activity内的话代码量可能会减少5倍,使用MVP模式代码量不降反增,而且理解力也不够好了。其实不然,这里只是举了一个很小的例子来说明,真正做项目遇到很复杂的逻辑和页面交互假如都放在activity中显然会写的一团糟,对项目后期维护、单元测试、以及代码理解力来说都会很糟糕,我们充分的把功能解耦,从长远角度来看显然是十分有利的,好了,MVP的基本流程就写到这里,作为自己的一个总结,也希望可以给他人做一份参考。