简化版Android MVP

看过mvp结构的人都知道,在官方版本的mvp里面有很多大量的接口定义,没错 就是接口,没次都要写大量的接口,时间久了会觉得很烦,这里简化了一个mvp的标准写法少了很多接口定义,至少我现在项目中正在这么使用,不过这个MVP目前还有一层没有挖掘,那就是M层,不过在看了[架构向] 谈Android中DTO -> VO的重要性文章以后,感觉可以用在现在的M层中,做DTO,这样让P层在拿到数据以后只专心处理逻辑,而不用判断太多的数据校验。

先来看看传统的MVP的结构走向图:

MVP

这次的简化来源于经过实践发现,大部分Presenter------>View的都只是铺铺数据,而本着一个View拥有一个Presenter的原则,所以简化过后的结构走向还是原来的结构走向,只是少了一点接口而已,也算的上是对MVP的一种简化的封装。
首先我们先来看看BasePresenter类:

public abstract class BasePresenter<T extends BaseView> {

    private WeakReference<T> weakReference;

    public BasePresenter(T baseView) {
        setView(baseView);
    }

    public T getView() {
        return weakReference!=null?weakReference.get():null;
    }

    public void setView(T view) {
        this.weakReference = new WeakReference<>(view);
    }

    public void recycle(){
        if(weakReference!=null){
            weakReference.clear();
            weakReference=null;
        }
    }
}

所有的Presenter都需要继承这个BasePresenter,更具结构类图,此类中需要依赖一个视图层的接口,因此在继承此类的时候通过泛型看到需要传入一个继承自BaseView接口的接口。没错Presenter层在向View通信的时候任然是需要依靠接口来通信的,这里取消了Presneter和Model的接口依赖关。从大部分实践上来看,感觉这两曾的的依赖关系并不是很重要,所以取消掉了,当然也有可能是我还没发现P与M之间的依赖好处。如果您有不同的看法可以在评论区留言,大家共同学习互相借鉴。在这里,M层只是一个简单的JavaBean。当然如果加上本文开头说的DTO,M曾的意义就体现出来了,不过目前还没有这么做。
在BasePresenter抽象类中,我们还看到了一个recycle()方法,这个方法是用来清楚View的依赖。因为很多时候Presenter中处理的都是异步耗时操作,如果此时用户等不耐烦了,推出了当然的界面,那么就很有可能会造成泄漏且如果您使用的是butterknife这个框架的话,挥发这个框架也会提共一个unbind()方法,如果这里不清楚View的依赖的话,当用户退出界面就会发生NullPointException的异常。所以BasePresenter中提供了这个方法。继承之后通过使用getView方法获取依赖的view,注意 使用前需要判断非空。

现在来看看BaseView接口:

public interface BaseView {

    void dialogShow(String message);
    void dialogShow();
    void dialogDissmiss();
}

这个接口很简单仅仅只是一个基类,定义了一些公共的方法如这里dialog的显示与关闭。
由于大部分View层都只是铺数据,区别只是数据的类型不一样,因此这里还提供几个普通的BaseView接口,
处理一种数据的接口

public interface BaseView1<T> extends BaseView{

    void getData(T data);
}

处理两种数据类型的接口:

public interface BaseView2<T,J> extends BaseView{

    void getData(T data);
    void getData2(J data);
}

等等。这只是偶尔用用的,因为我这里出现的平率比较多所以才加上这写接口的。其实只需要一个BaseView接口就好了,在定义View层接口的时候基础BaseView就行。

这里有一个使用的例子,一般项目都会有一个BaseActivity之类的东西。

public class BaseActivity<T extends BasePersent<? extends BaseView>> extends AppCompatActivity implements BaseView {
    public static String TAG;

    private T presenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TAG=getClass().getCanonicalName();
    }

    @Override
    protected void onDestroy() {
        if(presenter!=null){
            presenter.recycle();
        }
        super.onDestroy();
    }

    public T getPresenter() {
        return presenter;
    }

    public void setPresenter(T presenter) {
        this.presenter = presenter;
    }

    @Override
    public void showLoading(String message) {
        Log.i(TAG,"dialog show "+message);
    }

    @Override
    public void hideLoading() {
        Log.i(TAG,"dialog hiden");
    }
}

这里BaseActivity实现了BaseView接口,并实现了里面的公共方法(这里是dialog的显示与关闭)。在onDestory()方法中,现调用了presenter中的recycle()方法来释放引用,这样不管presenter中做了什么耗时操作只要在getView之前判断了非空,就避免了泄漏的风险,已经空指针异常的风险了。

在来看看我们View所依赖的Presenter

public class DemoPersent extends BasePersent<DemoPersent.DemoView> {

    Service service;

    public DemoPersent(DemoView baseView) {
        super(baseView);
        service=ZillApi.NormalAdapter.create(Service.class);
    }

    public void doOnClick(String classId){
        getView().showLoading("正在加载");
        //做了一部分的耗时操作
        service.getMainDate(classId, new CallBack() {
            @Override
            public void success(String str) {
                 //取消Dialog
                if(getView()!=null){
                    getView().hideLoading();
                }
                //处理一些数据.......
                //返回数据
                if(getView()!=null){
                    getView().updateBtn2(str);;
                }
            }
        });

    }
    public void  doSomthing(){
        String str="haha22222";
        getView().updateBtn1(str);
    }

  //Presener所以来的View
    public interface DemoView extends BaseView {

         void updateBtn1(String str);

         void updateBtn2(String str);
    }
}

下面看看具体的Activity

public class MainActivity extends BaseActivity<DemoPresenter> implements DemoPresenter.DemoView {

    TextView btn,btn1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //指定当前Activity需要的Presneter
        setPresenter(new DemoPresenter(this));

        btn= (TextView) findViewById(R.id.btn);
        btn1= (TextView) findViewById(R.id.btn1);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getPresenter().doOnClick("dsadas");
            }
        });

        btn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getPresenter().doSomthing();
            }
        });

    }

    @Override
    public void updateBtn1(String str) {
        btn.setText(str);
    }

    @Override
    public void updateBtn2(String str) {
        btn1.setText(str);
    }
}

如此在也不要担心泄漏的风险和空指针的问题了。还少些了很多接口,代码也简洁多了。在View值会看到很多傻瓜式的铺数据的过程。
在此结构的基础上,还可以引入DataBind以及本文开头说的DTO等进行进一步的简化。Model层还有很大的提升空间。

欢迎共同探讨更多安卓,java,c/c++相关技术QQ群:392154157
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容

  • 作者:李旺成 时间:2016年4月3日 “Android MVP 详解(下)”已经发布,欢迎大家提建议。 MVP ...
    diygreen阅读 128,846评论 86 1,321
  • 人笨学的慢啊。。抓紧学习MVP 网上MVP的学习资料也是多如牛毛,来看看谷歌爸爸是怎么教我们MVP的吧 项目介绍 ...
    hongjay阅读 2,669评论 1 21
  • http://tmi.yokogawa.com/cn/industries/industrial-consumer...
    dyg540阅读 147评论 0 0
  • 浩途最初吸引我的地方是看到了她的目的:培养一个,幸福一家,服务一群,带动一个地区,引领更多的人走上助人自助的成长之...
    净妍阅读 255评论 0 4
  • 蔡小名在走廊碰到经常给他换药的护士X20,她正好要下班,提议陪蔡小名走一段。 X20推着一辆独轮自行车,一直低着头...
    echo_1c53阅读 114评论 0 0