Android MVP架构封装



什么是MVP架构


  mvp是目前使用最为广泛的架构,其本质上是对mvc的升级使其更加适合Android开发,可以是代码结构更为清晰,解耦合,分离了视图逻辑和业务逻辑(便于修改需求).

MVP的核心思想就是分离业务逻辑层,使代码尽可能的解耦合,将视图交给V层,逻辑交给M层,业务交给P层


mvp优点

  • 解耦合 : 将业务,逻辑和视图分开,实现代码解耦合
  • 代码清晰 : 代码层次分明,数据层,表现层,逻辑层结构清晰
  • 方便修改需求: 当需要修改界面时,我们可以只对视图层进行修改,保留数据层

mvp三层含义

M层(model)数据逻辑层,用于操作数据库,对数据进行解析等一系列数据相关操作
P层(presenter)业务逻辑层,管理当前页面的业务逻辑,持有M和V层
V层(view)视图层,只管理数据的展示,布局等视图操作,持有P层

mvp和mvc的不同

  mvp与mvc最大的不同在于,mvc架构中M层持有了V层和C层,而且mvc中业务逻辑是放在V层中的,C层(controller)类似于一个路由,只用于触发某种事件或显示哪个view,不管理逻辑,业务和视图.这样一来导致V层中代码量较mvp更大.所以这两种架构其实各有各的好处,在后端代码中我们使用mvc架构更多.当然除了这两种架构以外还有MVVM等其他架构.

mvp模型图

Android MVP架构封装

mvc模型图

Android MVP架构封装

在mvp中使用LifeCycle绑定生命周期


  在mvp架构中,我们需要将V层的生命周期与P层进行绑定,这样我们就可以在v层被销毁时,解除相互引用,避免内存泄漏.而LifeCycle就是google推出的组织架构,可以在任何地方对Activity或者Fragment的生命周期进行监听.所以在mvp中引入这一组织架构,可以使我们的架构变得更为简洁.关于LifeCycle的详细说明,可以参考下面这篇文章.

LifeCycle架构



P层封装


  p层中我们需要完成对m层和v层的持有,以及在v层被销毁时解除对m和v层的持有避免内存泄漏.在这里我们通过弱引用构造了一个handler,这个handler就是用于p层与m层之间进行通信的类.通过modelResponse方法接收M层返回的消息.

通过LifeCycle实现P层接口IPresenter

P层接口中我们可以定义一些P层中常用的方法,还需要定义一些绑定V层生命周期的方法.

public interface IPresenter extends LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    default void OnCreate(@NonNull LifecycleOwner owner){}

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    default void OnDestroy(@NonNull LifecycleOwner owner){}

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    default void OnPause(@NonNull LifecycleOwner owner){}

    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    default void OnResume(@NonNull LifecycleOwner owner){}

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    default void OnStart(@NonNull LifecycleOwner owner){}

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    default void OnStop(@NonNull LifecycleOwner owner){}

    @OnLifecycleEvent(Lifecycle.Event.ON_ANY)
    default void OnLifeCycleChanged(@NonNull LifecycleOwner owner){}
}

P层具体实现

/**
 * 基础P层
 *
 * Created by db on 2018/9/22.
 */
public abstract class BasePresenter<M extends BaseModel,V extends IView> implements IPresenter{

    public V mView;
    public M mModel;

    @SuppressLint("HandlerLeak")
    public BasePresenter(V view){
        this.mView = view;
        this.mModel = binModel(getHandler());
    }

    /**
     *我们通过实现IPresenter中的OnDestroy方法来解除持有
     *
     * @param owner 生命周期管理者
     */
    @Override
    public void OnDestroy(@NonNull LifecycleOwner owner) {
        //解绑V层 避免导致内存泄漏
        mView = null;
        mModel.onDestroy();
        mModel = null;
    }

    public abstract M binModel(Handler handler);

    /**
     * 获取handler的方法
     *
     * @return BaseHandler
     */
    public Handler getHandler(){
        return new BaseHandler(this);
    }

    /**
     * 基础Handler 用于P层与M层通信
     */
    public static class BaseHandler extends Handler{

        //弱引用Activity或者Fragment 避免Handler持有导致内存泄漏
        private final WeakReference<BasePresenter> presenter;

        public BaseHandler(BasePresenter presenter) {
            this.presenter = new WeakReference<>(presenter);
        }

        @Override
        public void handleMessage(Message msg) {
            if(presenter.get()!=null&&presenter.get().mView!=null){
                presenter.get().modelResponse(msg);
            }
        }
    }

	//接收M层返回的消息
    public abstract void modelResponse(Message msg);
}


M层封装


  M层中,我们需要获取到P层中的handler,并通过该Handler构造了几个方法用于与P层进行通信.并且创建了一个销毁方法,用于解除对handler的持有(该方法是V层被销毁时通过P层调用的).

M层具体实现

/**
 * 基础M层
 *
 * Created by db on 2018/9/26.
 */
public abstract class BaseModel {

    private Handler mHandler; //获取P层中的Handler来通信

    public BaseModel(Handler handler){
        this.mHandler = handler;
    }

    /**
     * 用于解除持有
     */
    public void onDestroy(){
        mHandler = null;
    }

    /**
     * 发送消息到P层
     */
    public void sendMessage(Message message){
        if(mHandler!=null){
            mHandler.sendMessage(message);
        }
    }

    /**
     * 发送延时消息到P层
     */
    public void sendMessageDelayed(Message message,long delayedTime){
        mHandler.sendMessageDelayed(message,delayedTime);
    }

    /**
     * 发送空消息到P层
     */
    public void sendEmptyMessage(int what){
        mHandler.sendEmptyMessage(what);
    }

}



V层封装


  首先创建一个V层接口,基础Fragment和Activity都必须实现该接口,在这个接口中我们可以定义一些经常用到的基础方法.V层中我们需要完成对P层的持有,以及通过LifeCycle将V层生命周期绑定到P层,并且在V层被销毁时,解绑生命周期,通知P层解除相互持有.

V层接口

/**
 * V层接口
 *
 * Created by db on 2018/9/22.
 */
public interface IView {
    /**
     * 展示提示信息
     * @param message 要提示的信息
     */
    void showMessage(String message);

    /**
     * 显示加载进度.
     */
    void showProgress();

    /**
     * 隐藏加载进度.
     */
    void dismissProgress();

    /**
     * 判断是否有网络
     * @return 是否有网络
     */
    boolean hasNetwork(Context context);
}


基础Activity

/**
 * 基础V层 Activity
 *
 * Created by db on 2018/9/22.
 */
public abstract class BaseActivity<P extends BasePresenter> extends AppCompatActivity implements IView {

    public P mPresenter;

    public abstract P binPresenter();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //初始化mPresenter
        mPresenter = binPresenter();
        //绑定生命周期
        getLifecycle().addObserver(mPresenter);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //解绑P层 避免内存泄漏
        getLifecycle().removeObserver(mPresenter);
        mPresenter = null;
        //通知系统进行一次回收
        System.gc();
    }

    @Override
    public void showMessage(String message){
        Toast.makeText(getApplicationContext(),message,Toast.LENGTH_SHORT).show();
    }

    @Override
    public void showProgress(){

    }

    @Override
    public void dismissProgress() {

    }

    /**
     * 判断是否有网络
     * @param context 上下文
     * @return 是否有网络
     */
    @Override
    public boolean hasNetwork(Context context) {
        int netState = NetStateUtil.getNetworkState(context);
        if(netState!=NETWORK_FAIL){
            return true;
        }
        return false;
    }
}

基础Fragment

/**
 * 基础V层 Fragment
 *
 * Created by db on 2018/9/22.
 */
public abstract class BaseFragment<P extends BasePresenter> extends Fragment implements IView {

    public P mPresenter;

    abstract P binPresenter();

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //初始化mPresenter
        mPresenter = binPresenter();
        //绑定生命周期
        getLifecycle().addObserver(mPresenter);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        //解绑P层 避免内存泄漏
        getLifecycle().removeObserver(mPresenter);
        mPresenter = null;
        //通知系统进行一次回收
        System.gc();
    }

    @Override
    public void showMessage(String message){
        Toast.makeText(getContext(),message,Toast.LENGTH_SHORT).show();
    }

    @Override
    public void showProgress(){

    }

    @Override
    public void dismissProgress() {

    }

    /**
     * 判断是否有网络
     * @param context 上下文
     * @return 是否有网络
     */
    @Override
    public boolean hasNetwork(Context context) {
        int netState = NetStateUtil.getNetworkState(context);
        if(netState!=NETWORK_FAIL){
            return true;
        }
        return false;
    }
}


契约类


我们可以将M层,V层,P层接口放到一个类中,用于减少类的数量,也便于查看接口方法.

/**
 * 契约类
 * 
 * Created by db on 2018/10/7.
 */
public interface Contract {
    interface View{

    }
    interface Model{

    }
    interface Presenter{

    }
}


使用示例


  这里我做了一个模拟登录的示例,当然我们没有真的去请求登录接口,只是模拟了一遍从V层请求登录,通过P层调用M层请求方法,M层将数据回传给P层,然后P层通知V层更新的过程.这里我们使用的是系统的Message类来作为信息媒介,如果觉得还是很麻烦,我们可以对Message进行封装,这样在接收消息时也就可以不再做类型强转了,也就在根源上避免了类型强转错误.


V层使用示例

public class TestActivity extends BaseActivity<TestPresenter> {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //模拟请求登录
        mPresenter.login();
    }


    @Override
    public TestPresenter binPresenter() {
        return new TestPresenter(this);
    }

    public void loginReseponse(Message msg){
        showMessage((String) msg.obj);
    }
}

M层使用示例

public class TestModel extends BaseModel {

    public TestModel(Handler handler) {
        super(handler);
    }
    public void login(){
        //这里假装进行了模拟登录
        Message message = new Message();
        message.what = 0; //0表示请求成功
        message.obj = "登录成功"; //这里存放数据
        sendMessage(message);
    }
}

P层使用示例

public class TestPresenter extends BasePresenter<TestModel,TestActivity> {

    public TestPresenter(TestActivity view) {
        super(view);
    }
    @Override
    public TestModel binModel(Handler handler) {
        return new TestModel(handler);
    }

    @Override
    public void modelResponse(Message msg) {
        switch (msg.what){
            case 0:
                mView.loginReseponse(msg);
                break;
        }
    }
    public void login(){
        mModel.login();
    }

}


源码地址


MVP封装源码地址