/R2R2Mvp

项目开发基本架构 rxjava2+retrofit2+mvp demo

Primary LanguageJava

R2R2Mvp

项目开发基本架构 rxjava2+retrofit2+mvp


上个项目忙完第一版,在此对上个项目架构总结下,不断总结分析,才能发现结构的短板,才能搭出属于自己的最完美的架构


1.分包

------我的分包如下图:

这里写图片描述

adapter:放一些adapter类,属于view层的
api:放一些网络请求相关的类,如配置retrofit
base:放一些activity、fragment、presenter的基类
common:放一些全局都会用到的公共类,如application
model:我的model层只放了bean类,分为request和response,跟传统mvp的model不同,传统mvp的model层是请求网络数据,然后p层拿到m层和v层的引用,使m层和v层交互,但那样代码量太多了,每一个请求都要创建一个model类,为了简介,我就把请求网络数据直接放在了p层,在后面的代码中你会看到。
presenter:放presenter类
utils:放一些工具类
viewinterface:放view接口类
viewimpl:放view实现类
widget:放自定义view

------因为这个项目不大,界面不多,所以我采用此种分包,如果项目功能模块比较多的话,按功能模块分包比较好,结构清晰。下图是我之前做过的功能模块比较多的项目:

这里写图片描述


2.mvp

自2016年起,mvp框架一度兴起,越来越多的安卓开发者都选择用mvp框架来开发app。mvp结合rxjava和retrofit 简直爽的不要不要的,自从用了mvp结合rxjava和retrofi,代码简洁了,逻辑也清晰了,调用也优雅了,维护成本也低利了。公司的这个项目我是用mvp+rxjava2+retrofit2+butterknife。

此mvp框架用到了注解、工厂模式、代理模式来解决代码冗余、内存泄露(P在请求网络数据时,view(Activity或者Fragment)界面销毁,导致P仍然持有view的引用)、presenter生命周期以及数据存储问题;通过泛型将view和presenter绑定,可在view中直接调用getPresenter()获取presenter来请求网络数据,在presenter中可以直接通过调用getView()获取view来更新界面。请求网络用的是封装后的rxjava+retrofit,添加了网络请求和响应拦截器,网络请求和响应json可直接在在Android Studio中的Logcat中一目了然。

具体的源码实现我就不一一介绍了,感兴趣的朋友可以下载源码,自行查看;框架源码链接(https://github.com/isJoker/R2R2Mvp)。


3.使用

你的api

public interface WApi {

    //获取电影列表
    @POST("/PageSubArea/TrailerList.api")
    Flowable<MoiveListResponse> getMoiveList();

}

首先,先定义一个view接口IMoiveListView

/**
 * Created by JokerWan on 2017/12/11.
 * WeChat: wjc398556712
 * Function:
 */
public interface IMoiveListView extends IWanBaseView{

    void onLoading();

    void onLoadSucess(MoiveListResponse moiveListResponse);

    void onLoadFail(String msg);
}

Activity的使用(Fragment的使用类似),通过注解 @CreatePresenter创建Presenter

/**
 * Created by JokerWan on 2017/12/11.
 * WeChat: wjc398556712
 * Function:
 */
 
@CreatePresenter(MoiveListPresenter.class)//不要忘了这段代码
public class MainActivity extends AWanBaseActivity<IMoiveListView,MoiveListPresenter>
        implements IMoiveListView {

    @BindView(R.id.tv_moive_name)
    TextView tvMoiveName;
    @BindView(R.id.img_moive)
    ImageView imgMoive;

    @Override
    public int getViewLayoutId() {
        return R.layout.activity_main;
    }

    @Override
    public void initData(Bundle savedInstanceState) {
        if (null != savedInstanceState) {
            // TODO: 2017/12/11 数据恢复
        }
        getPresenter().getMoiveList();

    }

    @Override
    public void onLoading() {
        tvMoiveName.setText("数据加载中,请稍后...");
    }

    @Override
    public void onLoadSucess(MoiveListResponse     moiveListResponse) {
        MoiveListResponse.TrailersBean trailersBean = moiveListResponse.getTrailers().get(1);
        tvMoiveName.setText(trailersBean.getMovieName());
        Glide
            .with(this)
            .load(trailersBean.getCoverImg())
            .into(imgMoive);
    }

    @Override
    public void onLoadFail(String msg) {
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    }
}

presenter的使用

/**
 * Created by JokerWan on 2017/12/11.
 * WeChat: wjc398556712
 * Function:
 */

public class MoiveListPresenter extends AWanBasePresenter<IMoiveListView> {

    public void getMoiveList(){

        getView().onLoading();

        wApi.getMoiveList()
                .compose(ApiUtils.getScheduler())
                .subscribe(new ApiSubscriber<MoiveListResponse>() {
                    @Override
                    public void onNext(MoiveListResponse moiveListResponse) {
                        if(moiveListResponse != null) {
                            getView().onLoadSucess(moiveListResponse);
                        }
                    }

                    @Override
                    public void onError(Throwable t) {
                        getView().onLoadFail(t.getMessage());
                    }
                });
    }
}

4.demo运行后的效果

这里写图片描述