App架构设计实战一:初步引入MVP

App架构设计实战一:初步引入MVP

顺风笑嘻嘻,逆风mmp!

接着上一篇,上一篇其实隐含着一个比较大的问题,那就是MainActivity中,逻辑代码太多带来的直接问题就是看起来特别臃肿,如果后面继续添加功能,修改起来也麻烦,也就是扩展性也比较差。Activity大兄弟很气啊,mmp凭啥什么事情都交给我干,所以需要引入其他兄弟来分担下Activity的任务咯。

Android架构进化史

这里写图片描述

在Android远古时代,大家写代码都是直接在Activity里写。

中古时代,引入了M层,然后分为Model层和Control层。

现代的MVP模式(本篇不谈MVVM),又细化了引入了P层,Presenter层。mvp模式在某种程度来说跟现代的企业模式很像,那就是专业的事情交给专业的“人”来做。比如说View层只做展示操作(什么叫展示操作,即和xml中控件相关的操作,比如text.setText等)、Model层做数据处理操作、Presenter层做逻辑处理操作以及连接V和P,而我们把Activity当成View层。这样的好处是:

  • 代码层次比较分明;
  • 单元测试更加简单(相当于没有,因为我这里根本就不做单元测试);
  • 分解了原Activity的功能,轻量化Activity;
  • 相对更解耦,即后期扩展比较容易。

引入MVP

引入M

在我的理解中引入MVP层,一开始是从Model层开始引入的。可以这么写:

/**
 * <pre>
 *     作者   : 肖坤
 *     时间   : 2018/04/23
 *     描述   : m层,里面主要提供对数据的操作方法
 *     版本   : 1.0
 * </pre>
 */
public class MainModel
{
    private ApiService apiService = RetrofitHelper.createService(ApiService.class, false);

    //获取"tools/mockapi/440/yx0419"接口数据
    public Observable<ResEntity1.DataBean> getHttpData1()
    {
        return apiService.getHttpData1()
                .map(new HttpResultFunc<ResEntity1.DataBean>())
                .compose(RxSchedulers.<ResEntity1.DataBean>io_main());
    }

    //获取"tools/mockapi/440/yx04191"接口数据
    public Observable<ResEntity1.DataBean> getHttpData2()
    {
        return apiService.getHttpData2()
                .map(new HttpResultFunc<ResEntity1.DataBean>())
                .compose(RxSchedulers.<ResEntity1.DataBean>io_main());
    }

    //获取"tools/mockapi/440/yx04192"接口数据
    public Observable<ResEntity1.DataBean> getHttpData3()
    {
        return apiService.getHttpData3()
                .map(new HttpResultFunc<ResEntity1.DataBean>())
                .compose(RxSchedulers.<ResEntity1.DataBean>io_main());
    }

    //获取"tools/mockapi/440/token_expired"接口数据
    public Observable<ResEntity1.DataBean> getExpiredHttp()
    {
        return apiService.getExpiredHttp()
                .map(new HttpResultFunc<ResEntity1.DataBean>())
                .compose(RxSchedulers.<ResEntity1.DataBean>io_main());
    }

    //下载
    public Observable<ResponseBody> downLoadFile(String url, DownloadEntity downloadEntity)
    {
        ApiService apiService = RetrofitHelper.createService(ApiService.class,
                RetrofitHelper.getDownloadRetrofit(downloadEntity));
        return apiService.downLoadFile(url).subscribeOn(Schedulers.io());
    }

}

m层主要是对数据的一些处理,比较简单。

引入V和P

V层主要是对数据的一些展示,代码如下:

/**
 * <pre>
 *     作者   : 肖坤
 *     时间   : 2018/04/23
 *     描述   : V层
 *     版本   : 1.0
 * </pre>
 */
public interface MainView
{
    void getHttp1Suc(ResEntity1.DataBean dataBean);

    void getHttp1Failed(String errorMsg);

    void getHttp2Suc(ResEntity1.DataBean dataBean);

    void getHttp2Failed(String errorMsg);

    void getHttp3Suc(ResEntity1.DataBean dataBean);

    void getHttp3Failed(String errorMsg);

    void getExpiredSuc(ResEntity1.DataBean dataBean);

    void getExpiredFailed(String errorMsg);

    void downloadDisposable(Disposable disposable);
}

这里写图片描述

P层除了包括逻辑的处理外,还有一个很重要的作用就是连接V和M。因为在MVP模式中Model层和View层是不直接接触的。所以P层的构造方法如下:

public MainPresenter(MainView view, RxManager rxManager)
{
    this.viewWeakRef = new WeakReference<MainView>(view);
    this.rxManager = rxManager;
    mainModel = new MainModel();
}

因为MVP模式中V层一般都是Activity或者Fragment,属性系统有声明周期的组件,稍不注意就可能会引起内存泄漏(也就是内存没有及时回收),所以这里用一个弱引用来进行第一层规避。还有在这里初始化了Model。

P层代码整体如下:

/**
 * <pre>
 *     作者   : 肖坤
 *     时间   : 2018/04/23
 *     描述   : P层 作用:连接V和M,逻辑操作处理
 *     版本   : 1.0
 * </pre>
 */
public class MainPresenter
{
    private WeakReference<MainView> viewWeakRef;
    private RxManager rxManager;
    private MainModel mainModel;

    public MainPresenter(MainView view, RxManager rxManager)
    {
        this.viewWeakRef = new WeakReference<MainView>(view);
        this.rxManager = rxManager;
        mainModel = new MainModel();
    }

    public MainView getView()
    {
        return viewWeakRef.get();
    }

    public void getHttp1()
    {
        mainModel.getHttpData1().subscribe(new BaseObserver<ResEntity1.DataBean>(rxManager)
        {
            @Override
            protected void onErrorMsg(String msg)
            {
                getView().getHttp1Failed(msg);
            }

            @Override
            public void onNext(ResEntity1.DataBean dataBean)
            {
                getView().getHttp1Suc(dataBean);
            }
        });
    }

  //省略中间很多代码

    //暂停下载
    public void pauseDownload(Disposable disposable, String fileName)
    {
        DownloadManager.pauseDownload(disposable, fileName);
    }

    //取消下载
    public void cancelDownload(Disposable disposable, String fileName)
    {
        DownloadManager.cancelDownload(disposable, fileName);
    }

    //解绑view,并取消网络
    public void detachView()
    {
        if (viewWeakRef != null)
        {
            viewWeakRef.clear();
            viewWeakRef = null;
        }
        if (rxManager != null)
        {
            rxManager.clear();
        }
    }
}

我们在末尾有一个detachView方法,解绑view,这里做了第二层的内存泄漏的规避。这里的detachView一般在Activity中的onDestroy方法中调用:

@Override
protected void onDestroy()
{
    super.onDestroy();
    mainPresenter.detachView();
}

而Presenter的初始化一般都放在Activity的onCreate方法中:

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    rxManager = new RxManager();
    mainPresenter = new MainPresenter(this, rxManager);
}

这样整体各司其职,就很舒服了。有没有懂的胸低!

后话

其实我们在项目中要灵活运用MVP模式。比如我认为在中小型应用中,可以一个模块用一个P和一个M,因为真的没有必要每一个页面都给造一个Presenter一个Model和一个View。当然哦,每个页面的View是要单独要的。但是Model和Presenter真的可以用一个模块分别提供一个。有没有懂得兄弟,不用我告诉你要干嘛吧?刷波6。

github:Demo

以上。

上篇博客:App网络请求实战三:下载文件以及断点续载
下篇博客:
App网络请求实战四:rxjava操作符flatMap使用以及rxjava源码解析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值