MVP架构---基本使用篇
熟练用于MVP架构者这篇可以跳过
自己工作当中,涉及到APP开发的部分并不多,MVP+Retrofit+Rxjava这种模式其实在两年前就用的很多了,自己也利用WanAndroid写过一个这种架构模式的APP,而不是像以前MVC一把梭,总体来说好处多。除了本章讲MVP项目模式之外,还会涉及到谷歌最新推出的jetpack技术,作为记录自己学习的一个过程,如果有缘看到这篇文章,写的不妥之处也可以指出来。
MVP VS MVC
MVP想对比MVC,其实要多绕几个弯,性能上执行速度稍微有一点点影响,但是对于代码解耦性是非常强的。MVC以前都可以写在一个Activity里面,V就是Activity视图层,M是网络加载层也能写在Activity里,C层控制器比如setAdapter都能写在同一个Activity,如果业务量多 了,代码维护起来,会很困难,MVP会拆分出不同的模块,使得层次更清晰,当然对应的接口也会相应的增多。
Jetpack
是为了让安卓开发有自己完成的标准,避免大家开发东西的时候,都是用自己的内容,这样子做的好处,不同的APP(比如换家公司接手别人的APP)里面的东西是千奇百怪。没有一个标准,所以在18年在google开发者大会上面就发布了这个概念。https://developer.android.google.cn/jetpack?hl=zh_cn里面分了很多模块,个人比较对架构模块感兴趣,里面有数据绑定,Lifecycles,LiveData,ViewModel,WorkManager等等。这些东西到时候都会集成在MVP里面,也会涉及到原理,后续会分章节简单介绍。
把UI逻辑抽象成VIEW接口,把业务逻辑抽象层Present接口,Moudule还是原来的model
工程视图
image.png
我们假设有这个场景,就加载一个listview(懒得写RecycleView了),item就是左边一张图片,右边上下两行textview,纯粹用MVP怎样去加载。
这个item的类型我们就叫做Girl,我们在bean包里面新建一个Girl
package com.mvp.lianxi.com.bean;
public class Girl{
public int icon;
public String like;
public String style;
public Girl() {
}
public Girl(int icon, String like, String style) {
super();
this.icon = icon;
this.like = like;
this.style = style;
}
public int getIcon() {
return icon;
}
public void setIcon(int icon) {
this.icon = icon;
}
public String getLike() {
return like;
}
public void setLike(String like) {
this.like = like;
}
public String getStyle() {
return style;
}
public void setStyle(String style) {
this.style = style;
}
}
接下来我们写一个视图层view层,标示这个类的view最终要显示什么东西,同时写一个base视图层,这个base视图层是所有View到时候有的一个共性的东西,比如showerrormessage,方便后面扩展
public interface IBaseView {
void showErrorMessage(String msg);
}
然后我们写当前这个V视图层要做的东西,肯定是展示,可能展示一张图片,可能有进度条,可能获取视频资料,并且我们还要继承这个IBaseView
public interface IGirlView extends IBaseView{
//显示图片(回调函数)
void showGirlView(List<Girl> girls);
//加载进度条
//获取视频资料
}
到了这里我们的View层就写完了,下面写Model层,也叫数据层,网络请求的
首先我们在model包里面定义一个叫IGirlModel的接口,这个接口里面的方式是表示他要去做什么事情,肯定是去加载数据。
public interface IGirlModel{
void loadGirlData(OnLoadListener onLoadListener);
interface OnLoadListener{
void onComplete(List<Girl>girls);
}
}
为什么这里要写一个内部接口?你loadGirlData去做加载了数据之后,这些数据是有用的,肯定要回传过来,我们要求回传的目标就是一些列Girl类型的集合,拿到这样的数据后才能去给人家从而展示。
然后我们新建一个叫GirlModel的类,去实现这个IGirl接口真正意义上的去做事(模拟加载数据)
public class GirlModel implements IGirlModel{
@Override
public void loadGirlData(OnLoadListener onLoadListener){
//这里进行各种网络请求,现在没有依赖其他网络库,我模拟一些数据,就当网络请求了
//然后通过接口回调的方式回传
List<Girl> data = new ArrayList<>();
data.add(new Girl(R.drawable.f1, "一星", "****"));
data.add(new Girl(R.drawable.f2, "一星", "****"));
data.add(new Girl(R.drawable.f3, "一星", "****"));
data.add(new Girl(R.drawable.f4, "一星", "****"));
data.add(new Girl(R.drawable.f5, "一星", "****"));
data.add(new Girl(R.drawable.f6, "一星", "****"));
data.add(new Girl(R.drawable.f7, "一星", "****"));
data.add(new Girl(R.drawable.f8, "一星", "****"));
data.add(new Girl(R.drawable.f9, "一星", "****"));
data.add(new Girl(R.drawable.f10, "一星", "****"));
onLoadListener.onComplete(data);
}
}
到了这里我们的Model层就写完了,下面Present层,也叫交互层,要联系V和M的。
现在我们新建一个基础P层我们叫BasePresent,所有的present类都要去继承这个Basepresent,因为这个presetn到时候要attachview和detachview去获取和及时释放对象的。不可能每个Activity里面都手动调用一遍这个方法。所以要写一个BasePresenter这个基类。要注意的就是代码里面的引用最好用WeakReference弱引用。关于弱引用的好处可以搜集一下资料。这里用到了泛型,本来<>里面是<IGirlView>,目的是为了持有这个View我们才能去获取和释放对象。这个对象不一定是IGielView,可能会有很多种xxxView,因此我们用泛型来代替。如果写死了,这就没法用了。这个attachview(T view)和detachview()目的是要用在BaseAcvitiy这种基类里面的。
public class BasePresenter <T extends IBaseView>{
WeakReference<T>iGirlView;
public void attachView(T view){
iGirlView=new WeakReference<>(view);
}
public void detachview(){
if(iGirlView!=null){
iGirlView.clear();
iGirlView=null;
}
}
}
现在我们看真正的GirlPresenter要做的事情,肯定是要去继承BasePresenter的,这里注意了,上面的BasePresenter已经持有了左边的VIEW了啊,既然GirlPresenter要继承BasePresenter的话那GirlPresenter也持有了左边的View。因此这个GirlPresenter所需要的就是把右边的MODEL给联系起来
public class GirlPresenter<T extends IGirlView> extends BasePresenter<T>{
//持有右边的MODEL
IGirlModel iGirlModel=new GirlModel();
//执行UI逻辑
public void fetch(){
if(iGirlView.get()!=null&&iGirlModel!=null){
iGirlModel.loadGirlData(new IGirlModel.OnLoadListener(){
@Override
public void onComplete(List<Girl> girls){
//girls上面就是model来的数据
//再交给view
iGirlView.get().showGirlView(girls);
}
});
}
}
}
到了这里我们把P层写完了,这三者写完之后,我们需要通过Activity....去联系起来
上面讲到一个dettachview和attachview,我们完全可以把这两个逻辑写在BaseActivity里面,这样就不用在每个Activity的oncreat和ondestroey去调用,另外我们为了避免每次都在各种Activity...自己创建一个present,我们完全可以用抽象类,去写一个抽象方法,然后让子类去继承这个BaseActivity,就会复写这个方法,然后我们在这个方法里面写入具体产生present的逻辑就可以了,这样一来是很方便的。具体代码如下。
public abstract class BaseActivity<T extends BasePresenter,V extends IBaseView> extends AppCompatActivity{
//持有表示层
protected T presenter;
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
presenter=creatPresenter();
presenter.attachView((V)this);
}
public abstract T creatPresenter();
@Override
protected void onDestroy(){
super.onDestroy();
presenter.detachview();
}
}
BaseAvitiy两个泛型标示一个是持有了中间层,另外一个持有View层
现在我们新建一个Activity集成BaseActivity,中间层P帮我们把数据M数据也拿到了,直接V展示UI就行了。
public class MainActivity extends BaseActivity<GirlPresenter<IGirlView>, IGirlView>implements IGirlView{
ListView listView;
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView=findViewById(R.id.listview);
presenter.fetch();
}
@Override
public GirlPresenter creatPresenter(){
return new GirlPresenter();
}
@Override
public void showGirlView(List<Girl> girls){
Log.d("MainActivity", "girls:" + girls);
//表示层就会把数据填到girls上
listView.setAdapter(new GirlAdapter(this, girls));
}
@Override
public void showErrorMessage(String msg){
}
一个简单的MVP架构就搭建好了,个人认为从这个简单的写法更好理解MVP架构,当然,写法有很多,真实项目里面会写的更复杂写。目前很多公司大部分都是用的这种模式。下节继续分析在MVP模式下,一行代码切换网络加载框架
链接:https://pan.baidu.com/s/11OkQ5v1C7Su1_W7uOuF2bw
提取码:ttgb
复制这段内容后打开百度网盘手机App,操作更方便哦