浅析MVP设计模式

来源:互联网 发布:java根据ip获取运营商 编辑:程序博客网 时间:2024/05/16 07:46

一、何为MVP

说起MVP模式,必须先从MVC这种传统的设计模式说起,一般传统的app页面布局的设置逻辑和业务处理了逻辑都写在activity层中,这样随着项目的迭代,老的代码将也来越乱,每次需求更改,业务数据层的逻辑更改和界面层的逻辑更改都将在activity中修改,如果是自己写的还好,若是上个哥们的项目,而且还写的很乱的,那么你懂得。
先盗一张图,因为我们要用这张图来解释。

MVC模式中View层和Model层都跟controller层关联,每次业务逻辑的更改都基本要在同一个类中修改,众所周知,写代码不难,改代码那是灾难啊,特别还不是自己的写的代码,这个时候那种感觉你懂得。如果采用MVP的话,将业务逻辑Model层和视图层分开,那么该需求的时候我们操作就好做点。比如改页面的页面变化修改view层代码,model层变化在model层改,这样更清晰。理论离不开实战,接下来用代码层讲解吧。

二、工程

工程结构如下:


adapter不解释了,bean这个也不解释了,model为数据处理类,view为视图逻辑层,presenter为中间层负责链接俩层。

1、model层处理:

定义一个接口规范:IGirlModel
public interface IGirlModel {    void loadGirl(GrilOnLoadListener listener);    interface GrilOnLoadListener{        void onComplete(List<Girl> girls);    }}
接着是其实现类,负责填充数据:
public class GirlModelImpl implements IGirlModel{    @Override    public void loadGirl(GrilOnLoadListener listener) {        //加载数据        List<Girl> data = new ArrayList<>();        data.add(new Girl("刘亦菲","https://gss0.bdstatic.com/94o3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike116%2C5%2C5%2C116%2C38/sign=a38cb7e5af1ea8d39e2f7c56f6635b2b/c2fdfc039245d6884449b2faadc27d1ed21b2420.jpg"));        data.add(new Girl("杨幂","https://gss1.bdstatic.com/9vo3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike116%2C5%2C5%2C116%2C38/sign=4cd858ed9f0a304e462fa8a8b0a1cce3/d53f8794a4c27d1e63dc172d13d5ad6edcc43864.jpg"));        data.add(new Girl("唐嫣","https://gss2.bdstatic.com/9fo3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike180%2C5%2C5%2C180%2C60/sign=ac5b0fe02d381f308a1485fbc868276d/08f790529822720e3e87df227ecb0a46f31fab98.jpg"));        data.add(new Girl("景甜","https://gss0.bdstatic.com/94o3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike180%2C5%2C5%2C180%2C60/sign=c9b60227d52a6059461de948495d5ffe/30adcbef76094b363416f503a1cc7cd98c109d5c.jpg"));        data.add(new Girl("赵丽颖","https://gss3.bdstatic.com/7Po3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike150%2C5%2C5%2C150%2C50/sign=826890e23a01213fdb3e468e358e5db4/48540923dd54564e9d204002b0de9c82d1584f47.jpg"));        data.add(new Girl("Angelababy","https://gss1.bdstatic.com/-vo3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike116%2C5%2C5%2C116%2C38/sign=005e5fcd9aef76c6c4dff379fc7f969f/9358d109b3de9c8234db74636681800a18d843a4.jpg"));        data.add(new Girl("孙俪","https://gss3.bdstatic.com/-Po3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike80%2C5%2C5%2C80%2C26/sign=e82ca234a18b87d6444fa34d6661435d/203fb80e7bec54e76de10a1bb9389b504fc26aa1.jpg"));        //返回数据        listener.onComplete(data);    }}

2、View层处理

该类主要定义一些页面操作,由activity去实现完成
/** * 视图层接口 */public interface IGrilView {    /**     * 加载提示     */    void showLoading();    /**     * 显示数据     * @param data     */    void showGirls(List<Girl> girls);}

3、presenter层

主要负责链接俩层将逻辑串起来
public class GirlPresenter {    //View引用    IGrilView mGirlView;    //Model引用    IGirlModel girlModel =  new GirlModelImpl();    public GirlPresenter(IGrilView mGirlView) {        this.mGirlView = mGirlView;    }    //    public void fetch(){        //显示进度条        if (girlModel != null) {            //显示进度条            if (mGirlView != null) {                mGirlView.showLoading();            }            girlModel.loadGirl(new IGirlModel.GrilOnLoadListener() {                @Override                public void onComplete(List<Girl> girls) {                    //返回数据                    //显示到view层                    mGirlView.showGirls(girls);                }            });        }        //加载数据    }}

4、activity中调用

public class MainActivity extends AppCompatActivity implements IGrilView {    private ListView listView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        listView = (ListView) findViewById(R.id.lv);        new GirlPresenter(this).fetch();    }    @Override    public void showLoading() {        Toast.makeText(this, "正在加载中...", Toast.LENGTH_SHORT).show();    }    @Override    public void showGirls(List<Girl> girls) {        listView.setAdapter(new GirlAdapter(this,girls));    }}

5、优化

此时项目效果已将出来了,但是这种情况是存在问题的,问题就出在presenter层,该层持有view层的引用,而view层接口的实现都是activity,那么这时候就有内存泄漏了。怎么解决呢,其实简单的解决就是让view层的引用是弱引用,这样gc会在内存不足的时候将这个对象回收掉,这样就避免了内存泄漏,代码如下:
public class GirlPresenter {    //View引用//    IGrilView mGirlView;    WeakReference<IGrilView> mGirlView;    //Model引用    IGirlModel girlModel = new GirlModelImpl();    public GirlPresenter(IGrilView mGirlView) {        this.mGirlView = new WeakReference<IGrilView>(mGirlView);    }    //    public void fetch(){        //显示进度条        if (girlModel != null) {            //显示进度条            if (mGirlView != null) {                mGirlView.get().showLoading();            }            girlModel.loadGirl(new IGirlModel.GrilOnLoadListener() {                @Override                public void onComplete(List<Girl> girls) {                    //返回数据                    //显示到view层                    mGirlView.get().showGirls(girls);                }            });        }        //加载数据    }}

6、源码

源码地址