在开发的过程中,目前大多都是采用的MVP模式,MVP与之前的MVC模式基本是差不多的,都是对View和Model进行了抽取,但是MVC是把View与Model交互的来使用,耦合性相对较高,而MVP是把View与Model在Presenter层做交互,在View层完全没有Model的身影,这样降低了代码的耦合度,更有利于在后期对项目的维护。
我是自己这么理解的,Model做数据的处理,View做对视图的操作,在Presenter层进行数据与视图的处理。
根据官方的信息来看的话,大致是需要三个接口,三个类。
这三个接口分别是IModel,IView,IPresenter分别对应Model类,View,Presenter类
两个类分别是Model类,Presenter类,也就是说需要实现上面所说的对应的接口
还有一个数据Bean类,也就是网络请求数据解析的Bean(下面就不说这个类了)
下面再来一个一个的分析
IView接口中,主要就是对View(视图)功能的一个抽取,简单来说就是get/set方法,比如说对TextView的设置内容setText()的抽取,可以抽取出来写成一个方法 void setText(String str)这个方法就写在IView接口中,getText()也是同样的道理,具体的就看自己的需求是什么了。
IModel接口中,主要是对数据的一些操作,比如说获取网络数据,还是从数据库或者其他途径获取数据,说白了就是数据的存取。同样是需要我们自己定义一些方法,get/set方法比如说,我们可以从TextView上获取到一些字符串信息,通过IView中的get方法返回一个String,然后我们通过Model的方法来把这个数据做保存或者其他操作,我们可以在这个IModel中定义一个抽象的方法,setString(String str)来对数据进行存储或者是进行一些其他的操作。
在IPresenter接口中,因为是做数据与View的交互,所以我们可以定义一些方法,比如说,我们在Model中获取到数据然后把数据放入到View上面去,我们可以定义一个showData()的抽象方法,具体的实现在对应Presenter类中实现数据的交互,这个接口也可以不写,直接在Presenter类中实现具体的交互
上面的三个接口可以写在一个Contract的类中去,这样对自己的逻辑有一定的帮助(建议)下面是我自己的一个Demo中的部分代码,可以参考
public class MusicContract {
//view的接口
public interface IMusicView{
void setData(List<MusicBean.SongListBean> list);
}
//model的接口
public interface IMusicModel{
void getData(MusicModel.CallBack callBack);
}
//presenter接口
public interface IMusicPresenter{
void showData();
}
}
说完接口我们来看Model层中的实现类,上面我们定义了一个IModel接口,这里我们实现一下IModel接口,重写我们定义的方法,把具体获取数据的操作都在重写的方法中实现,例如:我们通过网络获取数据,在这里我们需要注意一下,因为通过网络获取数据的话可能会需要一段时间,所以最好定义一个接口,通过接口的回调,把获取的json字符串(网络获取的数据)放进新定义的接口中,那么我们上面定义的IModel接口中可能还需要再传进一个接口对象,也就是说setString(回调接口),方便我们的使用。
public class MusicModel implements MusicContract.IMusicModel {
@Override
public void getData(final CallBack callBack) {//重写的方法
String url = "";
//通过OkHttp获取网络数据
OkHttp3Utils.doGet(url, new GsonObjectCallback<MusicBean>() {
@Override
public void onUi(MusicBean musicBean) {
//接口的回调返回数据
callBack.setData(musicBean.song_list);
}
@Override
public void onFailed(Call call, IOException e) {
}
});
}
//自己定义的接口,用来回调数据
public interface CallBack{
void setData(List<MusicBean.SongListBean> list);
}
}
处理好数据以后,就需要我们对数据与View进行交互了,也就是对Presenter层的操作, 同样的,我们需要先实现IPresenter接口,重写接口中的方法,在这里我们还需要两个全局变量,IView的接口对象,Model类的对象,
当然还需要带有IView参数的构造函数,在构造函数中,给Model类创建实例,方便我们调用Model中的方法,下面的话就是在重写中的方法实现具体的操作,这里我自己理解的是,需要获取View中的数据,直接调用Iview的方法,需要把数据放到View中,通过Model对象获取到具体数据,再通过IView对象的set方法,把数据设置给具体的View
public class MusicPresenter implements MusicContract.IMusicPresenter {
//定义全局变量
private MusicContract.IMusicView view;
private MusicModel model;
//构造函数
public MusicPresenter(MusicContract.IMusicView view) {
this.view = view;
model = new MusicModel();
}
@Override
public void showData() {//重写的方法
//通过model对象调用获取网络数据的方法
model.getData(new MusicModel.CallBack() {
@Override
public void setData(List<MusicBean.SongListBean> list) {
//通过IView对象的set方法设置数据
view.setData(list);
}
});
}
}
我们所说的MVP,到目前为止,已经有了Model和Presenter,就剩下一个View层了,说来最简单的就是View层了,View层其实就是我们最熟悉的Activity和Fragment,只需要我们实现一下IView接口,重写其中的方法,当然不要忘了创建Presenter对象,毕竟我们还需要用到具体实现数据交互的方法,否则将毫无意义,还有就是在Activity被销毁的时候,需要把Presenter的对象置为空,避免数据返回的时候没有地方展示,导致程序奔溃(特别要注意)
public class MainActivity extends AppCompatActivity implements MusicContract.IMusicView {
private MusicPresenter presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//创建Presenter实例
presenter = new MusicPresenter(this);
presenter.showData();
}
@Override
public void setData(List<MusicBean.SongListBean> list) {
}
@Override
protected void onDestroy() {
super.onDestroy();
//在Activity被销毁的时候把Presenter重置为空,不然返回的数据没有地方存放,容易导致程序奔溃
presenter = null;
}
}