Android学习笔记MVP模式框架

来源:互联网 发布:linux 查看服务器编码 编辑:程序博客网 时间:2024/04/29 03:54

Android学习笔记MVP模式框架

1.MVP模式介绍:
在上一次学习中,我简单的介绍了MVC构架,这次我来简单的介绍下什么是MVP。对于MVP,他其实就是MVC的一个演化版本,MVP全称Model View Presenter。目前MVP在android应用开发中越来越重要了,相信不少的开发者也在各种讨论关于MVP的理论了。那么这个MVP模式他到底有哪些应用的好处呢?首先MVP能够有效的降低View的复杂性,避免业务逻辑被塞进View中,使得View代码优化了不少。MVP模式会解除View与Model的耦合,同时又带来了良好的可扩展性、可测试性,保证了系统的整洁性、灵活性。可能对于简单的应用,你会觉得MVP会稍微显得有点麻烦,因为他提出了各种各样的接口概念,是的整个应用充斥着零散的接口,但是对于比较复杂的应用来说,MVP模式是一种良好的构架模式,它能够非常好的组织应用结构,使得应用变得灵活
 
 
2. MVP简单结构图:

这里写图片描述

从上图可以看出,MVP模式很好的分离显示层和逻辑层,他们之间通过接口进行通信,降低耦合。理想化的MVP模式可以实现同一份逻辑代码搭配不同的显示界面,因为他们之间并不依赖于具体,而是依赖与抽象。这使得Presenter可以运用于任何实现了View逻辑接口的UI,使之具有更广泛的使用性,保证了灵活度。
 
3. MVP模式的三个角色:

3.1 Presenter——交互中间人

Presenter主要作为沟通View和Model的桥梁,它从Model层检索数据后,返回给View层,是的View和Model直接没有耦合,也将业务逻辑从View角色上抽离出来,相比MVC模式,就很好的减少了View中的逻辑实现代码。

 
3.2 View——用户界面

View通常是指Activity、Fragment或者某个View控件,它含有一个Presenter成员变量。通常View需要实现一个逻辑接口,将View上的操作通过会转交给Presenter进行实现,最后,Presenter调用View逻辑接口将结果返回给View元素。  

3.3 Model——数据的存储

对于一个结构化的App来说,Model角色主要是提供数据的存取功能。Presenter需要通过Model层存储、获取数据,Model就像一个数据仓库。更直白地说,Model是封装了数据库Dao或者网络获取数据的角色,或者两种数据获取方式的集合。

 
4. MVP的代码实现:

关于具体的实现我就不在这里重复写了,有想了解的大家可以参考我的这些MVP模式框架的代码:

Android-缓存网络图片(MVP模式)学习笔记

Android之SqliteDatabase(MVP模式)实现用户登录注册功能

Android MVP模式 解析JSON 显示到ListView上

 
5. 关于MVP与Activity、Fragment的生命周期:

综合上面的代码,我们可以很清除的知道,MVP有很多有点,例如易于维护、易于测试、松耦合、复用性高、健壮稳定、易于扩展,但是,由于Presenter经常性地执行一些耗时操作,例如,我们上述的缓存网络请求网络图片。由于Presenter持有了MainActity的强引用,如果在请求结束之前Activity被销毁了,那么由于网络请求还没有返回,导致Presenter一直持有MainActivity对象,是的MainActivity对象无法被回收,此时就会发生内存泄露。那么对于这种问题如何解决呢?答案是可以通过弱引用和Activity、Fragment的生命周期来解决这个问题。首先建立一个Presenter抽象类,我们把它命名为BaseAdapter,他是一个泛型类,泛型类类型为View角色要实现的接口类型。具体代码如下。

BasePresenter.java

public class BasePresenter<V extends ViewInter> {    protected WeakReference<V> weakReference;//View接口类型的弱引用    public void attach(V t){        weakReference = new WeakReference<>(t);//每次将需要关联的View接口类型的类与其建立联系    }    public void deAttach(){//如果Activity、Fragment等View控件销毁时调用该方法,解除他们之间的关联        if(weakReference != null){            weakReference.clear();            weakReference = null;        }    }    public boolean isViewAttached(){        return weakReference != null && weakReference.get() != null;    }    public V getView(){        if(weakReference != null){            return weakReference.get();        }        return  null;    }

以上的四个方法,分别是建立关联、解除关联、判断是否与View建立了关联、获取View。View类型通过Presenter的泛型类型传递过来,Presenter对这个View持有弱引用。通常情况下这个View类型应该是实现了某个特定接口的Activity或者Fragment等类型。接下来还需要创建一个BaseActivity基类,通过这个基类的生命周期方法来控制它与Presenter的关系。相关代码如下。

BaseActivity.java

public abstract class BaseActivity<V extends ViewInter,T extends BasePresenter> extends AppCompatActivity {    protected T basePresenter;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        basePresenter = getBasePresenter();        basePresenter.attach((V)this);    }    public abstract T getBasePresenter();    @Override    protected void onDestroy() {        basePresenter.deAttach();        super.onDestroy();    }}

BaseActivity含有两个泛型参数,第一个是View接口类型,第二个是Presenter的具体类型。通过泛型参数,使得一些通用的逻辑可以被抽象到BaseActivity类中。下面看看具体要使用的MainActivity类的实现。

MainActivity.java

//主界面启动,展示数据等。public class MainActivity extends BaseActivity<MainActivity,Presenter> implements ViewInter<Bean.NewslistBean> {    private String path = "http://apis.baidu.com/txapi/mvtp/meinv?num=10";    private GridView mGrid;    private MyAdapter adapter;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        init();        basePresenter.load(path);    }    private void init() {        mGrid = (GridView) findViewById(R.id.mGrid);    }    @Override    public Presenter getBasePresenter() {        return new Presenter();    }    private void showListData(List<Bean.NewslistBean> data) {        if (adapter == null) {            adapter = new MyAdapter(data, R.layout.list_item);            mGrid.setAdapter(adapter);        } else {        }    }    //通过presenter代理类为我们提供数据    @Override    public void getAdapterData(List<Bean.NewslistBean> data) {        showListData(data);    }}

通过上面的代码,大家可以看出,在BaseActivity中的onCreate方法中,会通过getBasePresenter方法创建一个具体的Presenter,这个Presenter的类型就是BasePresenter类型。构建Presenter之后调用attach方法与Activity建立关联。而在onDestory方法中,则会与Activity解除关联,从而避免内存泄露。有些人可能会问,如果在onDestory中解除了对Activity的引用,那么就没有必要再用弱引用了。对于这个问题的答案是,并不是在任何情况下Activity的onDestroy都会被调用,一旦这种情况发生,弱引用也能够保证不会造成内存泄露。而通过BaseActivity的封装维护Presenter与View关联关系的代码,使得子类可以避免重复的代码,上面的代码正是如此。Presenter的创建以及View建立关联等操作都被封装到BaseActivity中,消除了子类重复代码的同时又避免了Activity的内存泄露问题。所以,在以后的设计中,你都可以为Activity、Fragment等类型都建立一个类似这样的基类,这样一来你就可以将这种思想运用到更广阔的范围了。

最后,从整体效果来说,MVP是开发过程中非常值得推荐的构架模式,他能够将各组件进行解偶,并且带来了良好的扩展性、可测试性、稳定性、可维护性,同时使得每个类型的职责相对单一、简单,便面了大量的“胖”程序存在,例如数千行的Activity类。他有效的业务逻辑、数据处理等工作从Activity等View元素中抽离出来,使得每个类尽可能简单,同时每个模块能够独立进行演化。它的思想也非常好的体现了面向对象的设计原则。

1 0
原创粉丝点击