MVP 的搭建

xiaoxiao2021-02-28  18

前言: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基本的简单搭建。最后附上一张所理解的图片。

转载请注明原文地址: https://www.6miu.com/read-1450201.html

最新回复(0)