MVP 的搭建

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Bu_siliang/article/details/80506339

前言:MVP,很早就已经开始使用,最近打算写一下,来分享自己的所得(哈哈,话不多说看下面):


一: 什么是MVP :

 1:MVP模式是MVC模式的一个演化版本,MVP全称Model-View-Presenter。目前MVP在Android应用开发中越来越重要了。
在Android中,业务逻辑和数据存取是紧紧耦合的,很多缺乏经验的开发者很可能会将各种各样的业务逻辑塞进某个Activity、Fragment或者自定义View中,这样会使得这些组件的单个类型臃肿不堪。如果不将具体的业务逻辑抽离出来,当UI变化时,你就需要去原来的View中抽离具体业务逻辑,这必然会很麻烦并且易出错。
2.使用MVP的好处
  (1)MVP模式会解除View与Model的耦合,有效的降低View的复杂性。同时又带来了良好的可扩展性、可测试性,保证系统的整洁性和灵活性。
  (2)MVP模式可以分离显示层与逻辑层,它们之间通过接口进行通信,降低耦合。理想化的MVP模式可以实现同一份逻辑代码搭配不同的显示界面,因为它们之间并不依赖与具体,而是依赖于抽象。这使得Presenter可以运用于任何实现了View逻辑接口的UI,使之具有更广泛的适用性,保证了灵活度。
3.MVP模式的三个角色
  (1)Presenter – 交互中间人:Presenter主要作为沟通View与Model的桥梁,它从Model层检索数据后,返回给View层,使得View与Model之间没有耦合,也将业务逻辑从View角色上抽离出来。
  (2)View – 用户界面:View通常是指Activity、Fragment或者某个View控件,它含有一个Presenter成员变量。通常View需要实现一个逻辑接口,将View上的操作转交给Presenter进行实现,最后,Presenter 调用View逻辑接口将结果返回给View元素。

  (3)Model – 数据的存取:Model 角色主要是提供数据的存取功能。Presenter 需要通过Model层存储、获取数据,Model就像一个数据仓库。更直白的说,Model是封装了数据库DAO或者网络获取数据的角色,或者两种数据方式获取的集合。

二:注意事项

1:持有关系

 M 层 与 P 层互相持有

  P 层持有 V

  V 层 持有 P层;

 问题 1

 当页面(V)销毁时候,由于P层还持有V层的引用所以不会立即回收,finish(没有意义)--->内存泄漏

  方案:

 页面销毁时候 onDestory 时候 通知 P层 断开持有V层的引用 (presenter 置空,或者view置空 都能断开)

问题2:若JVm回收了View P层有在做耗时操作,完成后需要通知V层刷新UI, view 对象置空了(回收 置空)----->空指针异常

  方案:

p层向V层传递数据时候判断view是否为空

 三:基类封装

(1)BaseMVPActivity基类

package com.hdl.mvp.base;

import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;

/**
 * 实现mvp模式的公共activity类,所有使用mvpactivity页面都需要继承此类
 * <p>
 * 温馨提示:
 * 1、实际开发中需要将BaseMvpActivity继承的AppCompatActivity改成你自己的BaseActivity(如果有)
 * 2、如果页面再进去其他页面之后不需要了,一定要及时finish
 * <p>
 *
 *
 * @author HDL
 */

public abstract class BaseMvpActivity extends AppCompatActivity implements View.OnClickListener {
    private BasePresenter presenter = null;
    public Context mContext;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(getLayoutResId());
        mContext = this;
        presenter = bindPresenter();
        initView();
        initData();
    }


    /**
     * 返回资源的布局
     *
     * @return
     */
    public abstract int getLayoutResId();

    /**
     * 组件初始化操作
     */
    public abstract void initView();

    /**
     * 页面初始化页面数据,在initView之后调用
     */
    public abstract void initData();

    /**
     * 绑定presenter,主要用于销毁工作
     *
     * @return
     */
    protected abstract BasePresenter bindPresenter();

    /**
     * 如果重写了此方法,一定要调用super.onDestroy();
     */
    @Override
    public void onDestroy() {
        super.onDestroy();
        if (presenter != null) {
            presenter.onDestroy();
            presenter = null;
            System.gc();
        }
    }
}

(2)BaseMVPFragment

package com.hdl.mvp.base;


import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * 实现mvp模式的公共Fragment,所有使用mvpfragment都需要继承至这个类
 * <p>
 * 温馨提示:
 * 1、实际开发中需要将BaseMvpFragment继承的Fragment改成你自己的BaseFragment(如果有)
 * 2、如果页面再进去其他页面之后不需要了,一定要及时finish
 * <p>
 * Created by HDL on 2017/10/17.
 *
 * @author HDL
 */

public abstract class BaseMvpFragment extends Fragment {
    private BasePresenter presenter = null;
    public Context mContext;


    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mContext = getActivity();
        View view = View.inflate(mContext, getLayoutResId(), null);
        presenter = bindPresenter();
        initView(view);
        initData();
        return view;
    }

    /**
     * 返回资源的布局
     *
     * @return
     */
    public abstract int getLayoutResId();

    /**
     * 组件初始化操作
     *
     * @param view view
     */
    public abstract void initView(View view);

    /**
     * 页面初始化页面数据,在initView之后调用
     */
    public abstract void initData();

    /**
     * 绑定presenter,主要用于销毁工作
     *
     * @return
     */
    protected abstract BasePresenter bindPresenter();

    /**
     * 如果重写了此方法,一定要调用super.onDestroy();
     */
    @Override
    public void onDestroy() {
        super.onDestroy();
        if (presenter != null) {
            presenter.onDestroy();
            presenter = null;
            System.gc();
        }
    }
}
(3) BasePresenter
package com.hdl.mvp.base;

/**
 * 公共Presenter * Created by HDL on 2017/10/17.
 *
 * @author HDL
 */

public interface BasePresenter {
    /**
     * 当页面销毁的时候,需要把View=null,
     * 然后调用 System.gc();//尽管不会马上回收,只是通知jvm可以回收了,等jvm高兴就会回收
     */
    void onDestroy();
}

(4)公共接口回调

package com.hdl.mvp.base;

/**
 * 公共回调监听
 *
 *
 * @author HDL
 */

public interface BaseCallbackListener<T> {
    /**
     * 当任务开始的时候回调
     */
    void onStart();

    /**
     * 当任务成功的时候回调
     *
     * @param result 任务请求结果
     */
    void onNext(T result);

    /**
     * 当任务执行过程中出错的时候回调
     *
     * @param errorMsg 错误消息
     */
    void onError(Throwable errorMsg);
}

(5)其次为了接口的管理性,我们最好建一个公共接口类

package com.hdl.mvp.ui.login;

import com.hdl.mvp.base.BaseCallbackListener;
import com.hdl.mvp.base.BasePresenter;
import com.hdl.mvp.ui.result.LoginResult;

/**
 * MVP接口管理类
 *
 *
 * @author HDL
 */

public class LoginContact {
    /**
     * M     */
    public interface ILoginModel {
        /**
         * 实际登录的地方,调用服务器登录接口
         *
         * @param username         用户名
         * @param pwd              密码
         * @param callbackListener 登录结果回调
         */
        void login(String username, String pwd, BaseCallbackListener<LoginResult> callbackListener);
    }

    /**
     * V     */
    public interface ILoginView {
        /**
         * 显示提示消息
         *
         * @param msg
         */
        void showMsg(CharSequence msg);

        /**
         * 显示加载中
         */
        void showLoading();

        /**
         * 管理加载状态
         */
        void closeLoading();

        /**
         * 跳转到主页面(登录成功之后)
         */
        void toMainPage();
    }

    /**
     * P     */
    public interface ILoginPresenter extends BasePresenter{
        /**
         * 开始登录
         *
         * @param username 用户名
         * @param pwd      密码
         */
        void startLogin(String username, String pwd);
    }
}
到此 我们基本就完成了MVP基本的简单搭建。最后附上一张所理解的图片。


猜你喜欢

转载自blog.csdn.net/Bu_siliang/article/details/80506339
MVP