Android MVP模式的化简深入理解

       网上关于MVP的冗长教程已经很多了,自己结合所做的MVP项目尽量简洁,简单,大白话的方式记录心得,为了日后遗忘的差不多了能迅速把记忆抓起来。一图胜千言,先上图。图1是mvp的框架流程图:

                          

                                                                                   图1     

     简单介绍下MVP三剑客:Model,View, Presenter,重点会结合Demo去剖析。

     Model:  它是涉及数据管理的接口,简单的说,只要是代码处理数据,都会由这个Model来负责。

     View: 你能看到的都是View , 作为用户能看到手机上的界面都是View视图层,作用仅仅是绘制UI元素和响应UI操作,比如点击UI元素。

     Presenter:   Presenter是三剑客的核心部分,app的逻辑代码基本全写在Presenter中了,从图1就能看出来,它承上启下,联系着Model层和View层

     需要注意的是,View层不和Model层直接联系,需要Presenter为中介,上面说的理论毕竟有些泛泛之谈,结合下面的Demo继续具体的分析。

                                                 

                                                                               图2

     Demo实现的效果很简单,点击界面上的搜索按钮,会发送http协议获取某个城市的经纬度,当获取到http请求回执后,反序列化Json,然后重新绘制界面,显示经纬度。从MVP的模式去讲,这个包含搜索Button的,点击搜索后弹出的转圈等待界面就是View层,当响应点击事件之后,View层就会通知Presenter层,让Presenter去发送获取经纬度的http协议,并且在Presenter中监听http协议的回执,若协议收发成功,那么presenter就会通知View层去重新绘制UI。下面贴出具体代码进行理解

/**
 * Created by xjc on 2018/11/26.
 */

public interface MainPresenter {


    interface View extends BaseView {
        //通知界面(View层)刷新的逻辑函数
        void refreshViewMistakeIntruductionList( LocationResponseBean bean);
    }

    interface Model {
        //发送获取经纬度坐标协议
        void getLonLat();
    }

}

     一个Presenter是由两部分组成的:Presenter接口和Presenter的具体实现(Impl),Presenter接口中包含了两个interface:View和Model。 View接口的抽象方法就是声明了Presenter层和View层之间的联系,要和View之间有怎样的交互,比如上面View接口中的方法就是通知界面刷新。Model接口就是MVP中Model层要实现的功能,上述代码Model层中抽象方法就是为了发送经纬度的http协议。这样一目了然,这个Presenter的功能有两个,一是获取经纬度,二是通知界面重绘,但是具体怎么干,怎么一点点写出来,都会交给这个Presenter接口的实现类。

/**
 * Created by xjc on 2018/11/26.
 */

public class MainPresenterImpl extends BasePresenter<MainPresenter.View> implements MainPresenter.Model{

    private ApiHttpService apiHttpService;


    @Inject
    public MainPresenterImpl(ApiHttpService apiHttpService) {
        this.apiHttpService = apiHttpService;
    }


    @Override
    public void getLonLat() {
        JSONObject jsonObject = new JSONObject();
        try {
            jsonObject.put("a","大连");
        } catch (JSONException e) {
            e.printStackTrace();
        }
        //retrofit2.0发送http请求
        invoke(apiHttpService.fetchLocation(jsonObject.toString()),new Callback<LocationResponseBean>(){
            @Override
            public void onResponse(LocationResponseBean bean){

                mView.refreshViewMistakeIntruductionList(bean);
            }
        });
    }
}

  可以看到实现类继承并实现了presenter接口中的View和Model接口,若协议收发成功,那么会调Presenter接口中View interface的方法,来通知界面该做一些XX操作了

   mView.refreshViewMistakeIntruductionList(bean);

下面来看一下主界面(View层)

/**
 * Created by xjc on 2018/11/26.
 */
public class MainActivity extends IBaseActivity<MainPresenterImpl> implements MainPresenter.View {

    private Toast mToast = null;
    @BindView(R.id.tv_location)
    TextView tv_location;
    @BindView(R.id.btn_search)
    Button btn_search;


    @Override
    protected int getLayoutId() {
        return R.layout.activity_main;
    }

    @Override
    protected void loadData() {

    }

    @Override
    protected void initView() {

    }

    @Override
    protected void initInject() {
        DaggerMainComponent.builder().apiHttpModule(new ApiHttpModule()).build().injectMain(this);
    }


    @Override
    public void refreshViewMistakeIntruductionList(LocationResponseBean bean) {
        //获取到数据,取消转圈
        dismiss();
        //重绘text
        tv_location.setText(bean.getLat()+","+bean.getLon());

    }


    @OnClick(R.id.btn_search)
    public void  searchLocation(View view) {

        //发送http请求
        mPresenter.getLonLat();
        //转圈等待
        createLoading();
    }


    @Override
    public void setState(int state) {

    }
}

   可以看到主界面只实现了Presenter的View接口,这就是博客最开始的流程图中View层不能和Model层直接建立联系的具体代码实现,当Presenter实现类的 mView.refreshViewMistakeIntruductionList(bean)被执行的时候,作为子类的MainActivity中的覆写函数会被执行,取消转圈并且重绘UI

 @Override
    public void refreshViewMistakeIntruductionList(LocationResponseBean bean) {
        //获取到数据,取消转圈
        dismiss();
        //重绘text
        tv_location.setText(bean.getLat()+","+bean.getLon());

    }

     由此,MVP的一整套流程都在这个Demo中完美的实现了,这也是我认为搭建MVP项目最简单,最方便的写法。Demo已打包上传:https://download.csdn.net/download/crystal_xing/10811027,关于MVP中所用的依赖注入框架Dagger2,会用同样的Demo再写一篇新的博客进行总结分析。

   

猜你喜欢

转载自blog.csdn.net/Crystal_xing/article/details/84565272