之前一直对MVP模式理解的不清楚,今天整理一下,理清楚。mvp模式属于Android架构设计。

一.MVP模式介绍

M-Model-模型、V-View-视图、P-Presenter-表示器。

a 、View: 视图层,对应xml文件与Activity/Fragment;(用户交互相关的操作接口定义)

b 、Presenter: 逻辑控制层,同时持有View和Model对象;(相当于view和model的传话筒)

c 、Model: 实体层,负责获取实体数据(数据操作,通过接口将数据返回给presenter层)

1.  mvp模式

2.mvp原理图

二.MVP模式优点

三.MVP模式代码

一、基类

model基类,暂时没有什么东西,

/*** model的基类,进行数据获取与传输,presenter持有其引用,调用对应子类的方法* 通过接口返回数据给 presenter*/public abstract class BaseModel {}

view基类,有一些常用的方法,放在baseActivity里面实现,需要注意的是setPresenter方法,作用是在activity里面绑定对应的presenter,

public interface BaseView<P extends BasePresenter> {//通用的常见view互动方法,写在基类里面void showLoading();void hideLoading();void showError(String msg, int code);//view绑定presenter的方法,由baseactivity类来实现void setPresenter(P p);
}

presenter基类:这里面注释掉的是使用手动回收view对象的方式,后来改成用弱引用了,更优化,防止内存泄漏。

presenter里面有持有model对象,怎么初始化这个model对象,我想了好久,对比了好几个方法,刚开始是在presenter的构造方法里面,传递过来model对象,但是presenter的初始化,是在对应的activity里面,那样activity里面就要有model对象,虽然没有操作model的方法,但是感觉持有对象了,也不算完全解耦了,最后找到了这个方法,getGenericSuperclass,可以直接获取泛型参数类型的真实类型,反射出new 对象。

我的presenter对象是在对应的activity里面初始化的,没有直接在activity基类里面实例化,而是哪个activity需要对应的presenter的时候,在对应activity里面初始化,因为感觉有些小的activity里面不需要presenter等等,很简单的,就不需要都写了。

/*** presenter基类,持有view,model的引用,进行逻辑处理* 作为view和model的传话筒,持有 activity的应用,并且setpresenter使activity持有presenter的引用* <p>* presenter持有activity的引用,* 可以用根据绑定的activity周期,将activity引用手动制空的方式回收,* 还可以使用weakReference的方式。*/public abstract class BasePresenter<V extends BaseView, M extends BaseModel> {private M model;//    private V view;public WeakReference<V> mViewRef;//view持有activity的引用,防止内存泄漏,使用弱引用public BasePresenter(V view) {//  this.model = CreateUtil.getT(this, 1);
//通过反射获取model对象的方法不行,继承关系太多,获取不到相应的对象

// this.view = view; mViewRef = new WeakReference<V>(view); mViewRef.get().setPresenter(this); } public M getModel() { return model; } public V getView() { if (isAttach()) { return mViewRef.get(); } else { return null; } } public void onDetatch() { if (null != mViewRef) { mViewRef.clear(); mViewRef = null; } } private boolean isAttach() { return null != mViewRef && null != mViewRef.get(); } // public V getView() { // return view; // }// 和baseActivity里的生命周期绑定 public void onCreate() { } public void onStart() { } public void onResume() { } public void onPause() { } public void onStop() { } public void onDestroy() { model = null; // view = null; }}

/*** 内部获取第i个类型参数的真实类型 ,反射new出对象.但是最后我没有用这个方法,因为获取不到父类的参数类型对象,debug调了很久也不行,
*  下次有时间再改一下*/public class CreateUtil {public static <T> T getT(Object o, int i) {try {return ((Class<T>) ((ParameterizedType) (o.getClass().getGenericSuperclass())).getActualTypeArguments()[i]).newInstance();} catch (Exception e) {e.printStackTrace();}return null;}}

activity基类:setPresenter  showLoading hideLoading showError方法都是提前实现的view接口的,这样activity子类就不需要在每个都实现这些都需要的方法了,下面声明周期相关的,是前面presenter里面,如过没有使用使用弱引用获取view对象的方式,手动释放view对象要使用的方法。

/*** activity基类* 对应子类实现对应view接口的方法,持有presenter的引用*/public abstract class BaseActivity<P extends BasePresenter> extends Activity {private P presenter;public P getPresenter() {return presenter;}public void setPresenter(P presenter) {this.presenter = presenter;}public void showLoading() {}public void hideLoading() {}public void showError(String msg, int code) {}private Bundle bundle;private final String BUNDLE_KEY = "bundle_key";@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);bundle = getIntent().getBundleExtra(BUNDLE_KEY);if (bundle == null) {bundle = new Bundle();}//        if (null != presenter) {
//            presenter.onCreate();
//        }}public void startNextStepActivity(Class<? extends BaseActivity> activity) {Intent intent = new Intent(this, activity);intent.putExtra(BUNDLE_KEY, bundle);startActivity(intent);}public Bundle getBundle() {return bundle;}@Overrideprotected void onStart() {super.onStart();
//        if (null != presenter) {
//            presenter.onStart();
//        }}@Overrideprotected void onResume() {super.onResume();
//        if (null != presenter) {
//            presenter.onResume();
//        }}@Overrideprotected void onPause() {super.onPause();
//        if (null != presenter) {
//            presenter.onPause();
//        }}@Overrideprotected void onStop() {super.onStop();
//        if (null != presenter) {
//            presenter.onStop();
//        }}@Overrideprotected void onDestroy() {super.onDestroy();
//        if (null != presenter) {
//            presenter.onDestroy();
//        }}}

二、实现类

以login登录的方法为例子。这里使用了contract接口,是为了代码更整洁一些,将基类放一起。

contract接口:

public interface LoginContract {interface View extends BaseView<Presenter> {void onLoginSucess(String msg);}abstract class Model extends BaseModel {public abstract void requesetData(String data, ModelCallBack modelCallBack);}abstract class Presenter extends BasePresenter<View, Model> {public Presenter(View view) {super(view);}public abstract void login(String name, String password);}//model向presenter返回数据的接口,方法的数据类型根据需要自定义//这个接口也可以整理出通用的,不用每个contract都单独定义interface ModelCallBack {void onCallBack(String msg);}
}

model实现类:

public class LoginModelImpl extends LoginContract.Model {@Overridepublic void requesetData(String data, final LoginContract.ModelCallBack modelCallBack) {//进行网络数据操作等等,new Handler().postDelayed(new Runnable() {@Overridepublic void run() {modelCallBack.onCallBack("获取的数据");}}, 2000);}
}

presenter实现类:

public class LoginPresenterImpl extends LoginContract.Presenter {private LoginModelImpl model;public LoginPresenterImpl(LoginContract.View view) {super(view);model =  new LoginModelImpl();}@Overridepublic void login(String name, String password) {
    model.requesetData(name + password, new LoginContract.ModelCallBack() {

@Override public void onCallBack(String msg) { getView().onLoginSucess(msg); } }); }}view的实习类:重要的是oncreate里面 new 出来的对应的presenter对象,会调用到presenter基类里面绑定view.setPresenter方法,使得activity获取到presenter的对象。下面可以直接getPresenter()方法来获取presenter对象。

public class LoginActivity extends BaseActivity<LoginContract.Presenter> implements View.OnClickListener, LoginContract.View {private EditText etUserName;private EditText etPassword;private Button btnLogin;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();new LoginPresenterImpl(this);//实例化对应的presenter,activity绑定presenter对象setTitle("登录");}private void initView() {etUserName = (EditText) findViewById(R.id.et_user_name);etPassword = (EditText) findViewById(R.id.et_password);btnLogin = (Button) findViewById(R.id.btn_login);btnLogin.setOnClickListener(this);}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.btn_login:submit();break;}}private void submit() {String name = etUserName.getText().toString().trim();if (TextUtils.isEmpty(name)) {Toast.makeText(this, "用户名为空", Toast.LENGTH_SHORT).show();return;}String password = etPassword.getText().toString().trim();if (TextUtils.isEmpty(password)) {Toast.makeText(this, "密码为空", Toast.LENGTH_SHORT).show();return;}getPresenter().login(name, password);}@Overridepublic void onLoginSucess(String msg) {Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();}
}

最后,包的结构如下:

借鉴博客:

https://www.jianshu.com/p/3a17382d44de

MVP模式的理解和整理相关推荐

  1. java mvp模式_MVP模式入门(结合Rxjava,Retrofit)

    本文MVP的sample实现效果: 老规矩,在说对MVP模式的理解之前还是要再谈谈MVC模式,了解了MVC的缺点.我们才知道为什么要用MVP. 关于MVC的图解,我在网上找到了一些图.如下: MVC模 ...

  2. Android 浅谈MVP模式 一

    一直想记录下最近学习MVP模式的一些心得,又怕写的太渣,没办法,先写写然后及时更新. 我会粘贴一些代码,对于MVP模式的理解会在代码中详细注释 例一:闪屏界面判断是否已经登录 Presenter:对于 ...

  3. [vue] 说说你对MVC、MVP、MVVM模式的理解

    [vue] 说说你对MVC.MVP.MVVM模式的理解 MVVM用视图模型代替了MVP中的展示器,视图模型和视图实现了双向绑定,当视图发生变化的时候视图模型也会发生改变,当视图模型变化的时候视图也随之 ...

  4. MVP模式理解与使用

    目录 1.为什么使用MVP模式 1.1实例说明 2.如何使用MVP模式 2.1MVP实现之拆分 2.2MVP实现之接口通信 2.3MVP实现之功能仓库 3.MVP模式的优缺点 1.为什么使用MVP模式 ...

  5. Android:安卓学习笔记之MVP模式的简单理解和使用

    Android MVP模式的简单理解和使用 MVP模式 1. 为什么使用MVP模式? 1.1.实例说明 2.一步步让你理解MVP 2.1.MVP实现第一步, 将页面拆分为M/V/P三个模块 2.2. ...

  6. MVP 模式实例解析(转)

    reference pace: http://www.tracefact.net/Software-Design/MVP-Pattern-Explained.aspx 引言 可能有的朋友已经看过我翻译 ...

  7. MVP 模式实例解析

    MVP 模式实例解析 引言 可能有的朋友已经看过我翻译的Jean-Paul Boodhoo的 模型-视图-提供器 模式 一文了(如果没有,建议你先看下再看这篇文章,毕竟这两篇是紧密联系的).在那篇文章 ...

  8. Android MVP模式介绍和讲解

    作者:谭东 先给个MVP的出处链接:https://github.com/googlesamples/android-architecture/,出处就是google在github上的一个架构的开源例 ...

  9. MVP模式的相关知识

    MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示.作为一种新的模式,MVP与MVC有着一个 ...

最新文章

  1. 生成对抗网络(GAN)
  2. 2019秋招AI岗位竞争究竟有多激烈?
  3. Java AffineTransform入门
  4. Django + Uwsgi + Nginx 的生产环境部署项目知识点
  5. mysql连接串指定编码_MYSQL创建数据库时候直接指定编码和排序规则
  6. 责任心,内因还是外因?
  7. java泛型方法 通配符_Java泛型教程–示例类,接口,方法,通配符等
  8. 纯真IP数据库格式详解
  9. python读数据小数点_将excel数据读入pandas dataframe,精确到小数点后20位
  10. spring security oauth2.0 实现
  11. Firefox 的about:config
  12. WhatsApp拟取消服务订阅年费
  13. FriendStyle CSS
  14. 词法分析器|编译原理|陈火旺
  15. 用caffe框架做号牌识别笔记
  16. 嵌入式-stm32学习:使用固件库点亮LED
  17. high sierra php,mac os high sierra下搭建php多版本-php5.2+php5.6-nginx
  18. 发布功能完成02《ivx低代码签到系统制作》
  19. 翻棋子游戏与Nim游戏
  20. Linux 防火墙配置(iptables和firewalld)

热门文章

  1. 产品资讯 | mPaaS 10.1.68 适配 iOS 15
  2. 国家商务部点名京品高科,智能售卖系统独角兽成为行业标准
  3. 西部光伏电站复苏的曙光:电力交易
  4. 维度诅咒_释放或被诅咒
  5. TYPE C数据线的优势有哪些?
  6. 不知道怎么用?广百教你水性树脂涂料工业消泡剂EFKA8385破泡剂
  7. 数据泄露DLP 简单理解
  8. Vue动态路由路径重复以及刷新丢失页面问题
  9. scratch甲壳虫走迷宫 中国电子学会图形化编程 少儿编程 scratch编程等级考试一级真题和答案解析2023年3月
  10. 在微信实现唯一身份填报