从0开始搭建MVP+ViewModel框架的android应用01---MVPVM诞生记

Android MVPVM架构 一个基于MVPVM的架构,就是MVP+MVVM,Model层实现数据处理,ViewModel层DataBinding数据绑定,View只处理UI,详细流程可以看HomeFragment类 立即下载

对比MVC/MVP/MVVM

  • MVC:经典的模式,model,view,controller,比较好理解,但是有些缺点,承担View角色的模块包含了过多的业务逻辑
  • MVP:衍生于MVC,虽然View和业务解耦了,但是Presenter承担了太多任务
  • MVVM:采用DataBinding,数据的渲染自动反映在ViewModel上,同时也可以通过ViewModel获取数据,但是业务处理堆在一块。

基于此,想让处理不同事情的模块独立起来,通过接口解耦,Presenter只负责remote data/native data的获取,然后由ViewModel把数据跟View绑定起来,汲取MVP和MVVM所长,于是有了MVPVM。

补充:对于架构模式的搭建,没法说哪种更好,只有哪种更合适,不要局限于架构,结合业务特性,现有的人力和任务时间(采用架构代码量一般会增加,但是结构会清晰),选取适合的框架。

MVPVM

参照MVP模式,采取contract接口隔离的方式,分离出View,Presenter,ViewWapper;Activity/Fragment实现View接口,提供Context下的API调用等,Presenter实现当前模块的业务数据获取,ViewWrapper则负责把数据传递给ViewModel实现数据绑定,以及View传递的Event处理。如下图:
structure

抽离出Base类。

  • BaseView ——— 抽象出来的需要Context环境的调用接口
  • Presenter ——— 为实现架构搭建,由BasePresenter实现接口
  • ViewWrapper ——— 为实现架构搭建,由BaseViewWrapper实现接口
  • BaseActivity ——— 抽象出来的Base,即可由MvpVmActivity继承,也可由业务Activity继承
  • BasePresenter ——— 抽象出来的MvpVm架构的Presenter基类
  • BaseViewWrapper ——— 抽象出来的MvpVm架构的ViewWrapper基类
  • MvpVmActivity ——— 抽象出来的MvpVm架构的Activity基类
  • MvpVmFragment ——— 抽象出来的MvpVm架构的Fragment基类
  • DemoActivity
BaseView
public interface BaseView {

    public void setTitle(int titleId);

    public void setTitle(String title);

    public void showToast(int resId);

    public void showToast(String msg);

    public void showWaitDialog(int resId);

    public void showWaitDialog(String message);

    ....

}
Presenter
public interface Presenter<V, VW> {
    void attachView(V view);

    void setViewWrapper(VW viewWrapper);

    void detachView();
}
ViewWrapper
public interface ViewWrapper<V, D> {
    void attachView(V view);

    void detachView();

    void setBinding(D dataBinding);

    void onBind();
}
BaseActivity
public class BaseActivity<D extends ViewDataBinding> extends AppCompatActivity implements BaseView {

    ...

    protected D dataBinding;
    protected BaseActivity activity;
    private BaseActivityDataBinding baseBinding;

    protected <D extends ViewDataBinding> D generateDataBinding(@LayoutRes int layoutResID) {
        D binding;
        if (hasToolBar()) {
            baseBinding = DataBindingUtil.setContentView(this, R.layout.activity_base);

            ...

            LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            binding = DataBindingUtil.inflate(inflater, layoutResID, baseBinding.contentLayout, true);
        } else {
            binding = DataBindingUtil.setContentView(this, layoutResID);
        }
        activity = this;

        ...

        return binding;
    }
}

generateDataBinding替换一般情况下调用的setContentView(int layoutId),在业务Avtivity中第一步调用dataBinding = generateDataBinding(R.layout.xxx)即返回对应layout的DataBinding,用法后面demo中将会介绍。

BasePresenter
public class BasePresenter<V, VW> implements Presenter<V, VW> {

    public V view;
    protected VW viewWrapper;
    ...

    @Override
    public void attachView(V view) {
        this.view = view;
    }

    @Override
    public void setViewWrapper(VW viewWrapper) {
        this.viewWrapper = viewWrapper;
    }

    @Override
    public void detachView() {
        view = null;
        viewWrapper = null;
        ...
    }

    ...

}
BaseViewWrapper
public class BaseViewWrapper<V, D extends ViewDataBinding> implements ViewWrapper<V, D> {
    protected V view;
    protected D dataBinding;

    @Override
    public void attachView(V view) {
        this.view = view;
    }

    @Override
    public void detachView() {
        view = null;
        if (dataBinding != null) {
            dataBinding.unbind();
            dataBinding = null;
        }
    }

    @Override
    public void setBinding(D dataBinding) {
        this.dataBinding = dataBinding;
        onBind();
    }

    @Override
    public void onBind() {

    }

}

onBind方法由业务ViewWrapper实现,具体操作为DataBinding的数据绑定,以及listener等事件的设置,会在后续博客中详细介绍。

MvpVmActivity
public abstract class MvpVmActivity<P extends BasePresenter, VW extends BaseViewWrapper, D extends ViewDataBinding>
extends BaseActivity<D> {

    protected P presenter;
    protected VW viewWrapper;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        presenter = createPresenter();
        viewWrapper = createViewWrapper();
        if (presenter != null && viewWrapper != null) {
            presenter.setViewWrapper(viewWrapper);
        }
    }

    protected abstract P createPresenter();

    protected abstract VW createViewWrapper();

    @Override
    protected void onDestroy() {
        if (presenter != null) {
            presenter.detachView();
        }
        if (viewWrapper != null) {
            viewWrapper.detachView();
        }
        if (dataBinding != null) {
            dataBinding.unbind();
            dataBinding = null;
        }
        super.onDestroy();
    }
}

createPresenter和createViewWrapper由业务Activity继承实现,实例化对应业务的Presenter和ViewWrapper,后续博客会详细介绍。

MvpVmFragment
public abstract class MvpVmFragment<P extends BasePresenter, VW extends BaseViewWrapper, D extends ViewDataBinding>
    extends BaseFragment<D> {

    protected P presenter;
    protected VW viewWrapper;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        presenter = createPresenter();
        viewWrapper = createWrapper();
        if (presenter != null && viewWrapper != null) {
            presenter.setViewWrapper(viewWrapper);
        }
    }

    protected abstract P createPresenter();

    protected abstract VW createWrapper();

    @Override
    public void onDestroyView() {
        if (presenter != null) {
            presenter.detachView();
        }
        if (viewWrapper != null) {
            viewWrapper.detachView();
        }
        if (dataBinding != null) {
            dataBinding.unbind();
            dataBinding = null;
        }
        super.onDestroyView();
    }
}

createPresenter和createViewWrapper由业务Activity继承实现,实例化对应业务的Presenter和ViewWrapper,但是DataBinding实例的获取与在Activity中略有不同,是在onCreateView中获取的,后续博客会详细介绍。

DemoActivity
public class MvpVmDemoActivity extends MvpVmActivity<MvpVmDemoPresenter, MvpVmDemoViewWrapper, MvpVmDemoDataBinding>
    implements MvpVmDemoContract.View {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        dataBinding = generateDataBinding(R.layout.activity_mvpvm_demo);
        if (viewWrapper != null) {
            viewWrapper.setBinding(dataBinding);
        }
        presenter.fetchData();
    }

    @Override
    protected MvpVmDemoPresenter createPresenter() {
        return new MvpVmDemoPresenter(this);
    }

    @Override
    protected MvpVmDemoViewWrapper createViewWrapper() {
        return new MvpVmDemoViewWrapper(this);
    }

    ...

}

从代码中可以看到,在onCreate第一步就是生成对应的DataBinding实例(关于DataBinding会在后续博客中专门讲一次),然后设置给ViewWrapper,实现数据绑定关系,在createPresenter和createViewWrapper中实例化对应业务的presenter和viewWrapper。

截至到此,MVPVM的Base框架就大体搭起来了,后续还会更新基于此框架的业务细节实现(Adapter、RecyclerView、DataBinding的高级用法以及网络请求框架Retrofit二次封装等)

才疏学浅,板砖轻拍,代码还会陆续更新下去,查看源码请点击:

代码地址

android MVP和MVPVM 架构Demo 立即下载

相关推荐

MVP-VM实践

引入VIewModel 减轻对P对V的操作 protected fun vmProviders(modelClass: Class): T { val viewModel: BaseViewModel if (mContext is FragmentActivity || mContext is Fragment) { viewModel = if (mContext is BaseActivity) { ViewModelProviders.of(mContext as FragmentActivity).get(modelClass) } else { ViewModelProviders.of(mContext as Fragment).get(modelClass) } } else { viewModel = ViewModelProvider.AndroidViewModelFactory.getInstance(App.getInstance()).create(modelClass) } // 监听viewModel被销毁时 也销毁presenter viewModel.setClearedListener(object : BaseViewModel.ViewModelClearedListener { override fun onCleared() { onDestroy() } }) initCommon(viewModel) return viewModel

MVPVM模式介绍

一、概述 MVPVM即:Model-View-Presenter-ViewModel。此模式是MVVM和MVP模式的结合体。但是交互模式发生了比较大的变化。 MVVM参考本博客文章: iOS-MVVM-模式介绍 MVP参考本博客文章: MVP模式介绍  二、原理: Presenter同时持有View、

有志者事竟成-程序员也可以创造优雅的艺术 1615

逆向实战:基于内存态匿名段分析的 DexProtector 检测绕过策略

本文深入探讨了针对DexProtector加固方案的Frida检测绕过策略。通过分析运行时动态加载到匿名内存段的核心检测逻辑,提出了一套基于内存态分析、定位并转储匿名可执行段,进而通过精准Hook与“等式化替换”等技术实现稳定绕过的实战方法。该方法不仅适用于DexProtector,也对采用类似内存隐藏技术的加固方案具有参考价值。

ik678901的博客 516

android view wrapper,Android开源项目 RecyclerViewHelper

1.写在前面2019年的第一篇文章,分享一个自己写的开源项目,主要是对RecyclerView控件的一些常用功能封装, 包括(上拉加载更多、头尾布局、拖拽排序、侧滑删除、侧滑选择、万能分割线)。RecyclerViewHelper主要使用了装饰者模式对项目原有的Adapter进行功能扩展,不会影响项目的原有结构,集成和修改都非常方便,一起来看下。2.引入依赖库在项目根目录的build.gradle...

weixin_32701893的博客 243

RS485 MODBUS转PROFINET网关案例丨汇川变频器接入到1200 PROFINET

本案例介绍的是用北京小疆智控(北京)技术有限公司生产的GW-PN5003型MODBUS RTU转PROFINET网关将汇川变频器接入西门子PLC1200 PROFINET网络的使用方法。

bjxjzk的博客 1884

(程序设计方法与实践)达拉崩吧的酒宴

达拉崩吧的酒宴 Description 很久很久以前,巨龙突然出现,带来灾难带走了公主又消失不见,王国十分危险,世间谁最勇敢,一位勇者赶来大声喊:“我要带上最好的剑,翻过最高的山,闯进最深的森林,把公主带回到面前”……最后,英雄 达拉崩巴斑得贝迪卜多比鲁翁 ,他战胜了巨龙 昆图库塔卡提考特苏瓦西拉松 ,国王把公主 米娅莫拉苏娜丹妮谢莉红 嫁给了 达拉崩巴斑得贝迪卜多比鲁翁 。 于是国王第二天要在 蒙达鲁克硫斯伯古比奇巴勒城 举办酒宴,一共准备了 N 桶酒。此时一位忠诚的仆人来报,有人在其中一桶酒里下毒,

What_If_I的博客 894

视图

什么是视图? 视图的任务就是将入口函数的返回值(一个Java对象)渲染到 HTTP 响应流中。 现在 Nutz.Mvc 自带的主要视图有 JSP - 采用 JSP 模板输出网页Redirect - 客户端重定向Forward - 服务器端中转Json - 将对象输出成 Json 字符串void - 什么都不做Raw - 二进制输出,图片输出,文件下载等 当然你还可以根据需要

ma_wang_bo的博客 680

ICCompiler II实战:从NDM生成到APR流程的完整避坑指南

本文是一份针对ICCompiler II(ICC II)后端物理实现流程的实战避坑指南。文章详细解析了从NDM库生成、设计初始化、布局规划到时钟树综合与布线的完整APR流程,重点分享了各环节的常见陷阱、精细化配置命令与调试经验,旨在帮助工程师高效达成PPA目标,确保设计一次成功。

p4q5r6s7t的博客 533

Android MVPVM架构实践

简书地址:http://www.jianshu.com/p/b53e1450ca8f 前言写Android也有一段时间了,始终没有找到一种优雅流畅的Android架构模式,前不久看了google关于mvp架构的范例,甚好,建议仔细观摩一下:https://github.com/googlesamples/android-architecture。这篇文章也是参考了google的写法加上自己的理解和实践.........

myterabithia的博客 1163

反制反心理特征的研究

抓牛股

m0_58032574的博客 909

光电系统光轴校准与偏差控制实战指南

光轴作为光电系统的空间基准坐标系,直接影响多光谱传感器的协同工作精度。在包含可见光、红外与激光测距的复合系统中,光轴偏差会导致目标识别误差与打击精度下降。通过机械基准建立、光学通道粗调和多光谱协同校准等工厂级标定流程,结合千米靶标法、星点校准法等野战应急方案,可有效控制光轴偏差。典型应用场景中,温度补偿与振动抑制技术能维持光轴稳定性,如某舰载系统通过500Hz高频视觉伺服实现0.3mrad振动补偿。掌握这些光轴标定与保持策略,对提升光电系统在侦察、测距等场景的实战性能具有关键价值。

weixin_36149538的博客 277

一、什么是 mvvm? MVC、MVP、MVVM三种模式的区别与详解

MVC、MVP、MVVM都是常见的软件架构模式。MVC(Model-View-Controller)架构模式中,将应用程序分为三个主要部分:模型(Model)、视图(View)和控制器(Controller)。Controller负责处理用户交互和调度业务逻辑,View负责显示数据,Model负责数据的存储和逻辑处理。MVP(Model-View-Presenter)架构模式,类似于MVC,但将View和Model的交互逻辑抽象到了Presenter中。

qq_44849312的博客 1万+

S7-1200PLC 与温控仪表Modbus RTU通信

硬件:cpu 1214C 目的:通过Modbus RTU协议,实现对温控仪表的控制 软件:Portal V14SP1

weixin_43922025的博客 3万+

android view wrapper,GitHub - Lerist/ViewWrapperEditText: A View wrapper for EditTexts in Android. A...

ViewWrapperEditTextA View wrapper for EditTexts in Android. Add Views inside/outside EditTexts using this library##Setuprepositories {maven {url "http://dl.bintray.com/aditya2705/maven"}}dependencies...

weixin_39964833的博客 140

Stanford Dogs 犬类识别实战:基于 YOLOv8 的 120 类目标检测与图形界面实现

本项目通过YOLOv8实现了Stanford Dogs数据集的目标检测功能,完整包含了数据准备、模型训练、检测推理、图形界面四大模块。初学者使用YOLOv8n(nano版)加速训练,熟悉流程后可切换到YOLOv8s/m。图像上传与检测可进一步增强,例如显示识别框、标注标签。可以添加模型选择、检测阈值调整等功能,提升实用性。通过网盘分享的文件:基于yolov8的狗类品种识别系统链接: https://pan.baidu.com/s/1UYV4h2WnK1RxWWKoPrS-RA?

FJN110的博客 86

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

vue常见问题 MVVM、MVC、MVP的区别总结

vue常见问题 MVVM、MVC、MVP的区别总结1.MVC2.MVVM3.MVP 什么是MVC、MVP、MVVM? MVC、MVP和MVVM是三种常见的软件架构设计模式,主要通过分离关注点的方式来组织代码结构,优化开发效率。 在开发单页面应用时,往往一个路由页面对应了一个脚本文件,所有的页面逻辑都在一个脚本文件里。页面的渲染、数据的获取,对用户事件的响应所有的应用逻辑都混合在一起,这样在开发简单项目时,可能看不出什么问题,如果项目变得复杂,那么整个文件就会变得冗长、混乱,这样对项目开发和后期的项目维护是

$狴犴^的博客 737

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

MVC、MVP以及MVP+VM

文章目录MVC模式MVP模式MVP+VM模式总结 MVC模式 MVC模式的结构分为三部分,实体层Model,视图层View和控制层Controller。 工作原理:当用户触发事件,View层会发出指令到Controller层,由Controller层去通知Model层更新数据,Model层更新完数据后直接显示在View层上。 在Android工程中,View层对应xml布局文件,Controll...

陈德山 793

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

MVC,MVP,MVPVM(一)实践之路

简介 分别使用MVC,MVP,MVP+VM,实践具体需求,对比优劣,逐步优化。 需求 实现我的押金页面,包含未缴纳,已缴纳,免押金3种状态 1.顶部title:3种状态展示不同文案; 2.金额:已缴纳,未缴纳状态金额字号,色值不同;免押金状态不展示; 3.底部tips:已缴纳,免押金状态展示不同文案;已缴纳状态,不展示; 4.按钮:未缴纳,已缴纳状态,文案,及点击事件

listen2code的博客 1735

MVC/MVP/MVVM的理解

Model: 业务处理和存储,数据更新后更新 View: 人机交互接口,一般为展示给用户的界面 MVC Controller控制层: 负责连接Model层和View层,接受并处理View层触发的事件,并在Model层的数据状态变动时更新View层 思路: View层通过事件通知到Controller层,Controller层经过对事件的处理完成相关业务逻辑,要求Model层改变数据状态,Mo...

飞翔的熊blabla 364

MVPVM架构模式详解

MVPVM架构模式通过结合MVP和MVVM的优点,为开发者提供了一种灵活且强大的解决方案,特别适用于复杂的企业级应用。它通过清晰的职责划分和灵活的数据绑定机制,提高了代码的可维护性和可测试性。尽管MVPVM在架构复杂性和学习曲线上有一定挑战,但对于需要长期维护和团队协作的大型项目来说,这种投资通常是值得的。随着技术的发展,MVPVM架构也在不断演进,以适应新的开发范式和应用场景。在选择架构模式时,开发团队应根据项目规模、复杂度、团队经验和业务需求,决定是否采用MVPVM或其变体。

冰茶的博客 1092

MVC,MVP和MVVM架构解析

1.使得M,V,VM的解耦更加彻底,在mvp模式中,p需要持有V的引用,才能去刷新UI,在MVVM模式中,View和Model使用databingding进行双向绑定,一方改变会直接通知另外一方,使得viewModel能专注于业务逻辑的处理,而不需要去关心UI刷新。客户端开发最常用的重用时View,但是数据双向绑定技术,让你在一个View都绑定了一个model,不同模块的model都不同,那就不能简单重用View了。项目结构更加低耦合。1.解耦,区别于MVC不会产生巨量代码,区别于MVP不会产生大量接口。.

java521666的博客 1333

Android架构之MVC,MVP与MVVM

概述MVP(Model-View-Presenter)是传统MVC(Model-View-Controller)在Android开发上的一种变种、进化模式。主要用来隔离UI、UI逻辑和业务逻辑、数据,创建松散耦合并可重用的对象。我们知道View层是容易变化且多种多样的,业务逻辑也是多种多样的,与传统的MVC相比,P充当了C的作用. Model存储数据,View表示Model的表现,Presente

BoBoMEe 2177

java mvc mvp_MVC,MVP,MVPVM(一)实践之路

文章目录简介分别使用MVC,MVP,MVP+VM,实践具体需求,对比优劣,逐步优化。需求实现我的押金页面,包含未缴纳,已缴纳,免押金3种状态1.顶部title:3种状态展示不同文案;2.金额:已缴纳,未缴纳状态金额字号,色值不同;免押金状态不展示;3.底部tips:已缴纳,免押金状态展示不同文案;已缴纳状态,不展示;4.按钮:未缴纳,已缴纳状态,文案,及点击事件都不相同;我的押金页面.pngMVC...

weixin_42367582的博客 237

说说MVP模式

初看MVP模式时被它复杂的包含,继承,接口搞晕,View中有Presenter,Presenter中又有View,View又要抽象出IView,View又调用Presenter的方法,Presenter又调用IView的方法.花了点时间算是搞明白了,这里说说自己的理解. 关于MVP模式文章一搜一大把.建议先看看这些文章. Artceh http://www.cnblogs.com/...

200

MVC MVVM MVP Backbone 互动模式 架构模式总结分析

一、MVC MVC模式的意思是,软件可以分成三个部分。 视图(View):用户界面。 控制器(Controller):业务逻辑 模型(Model):数据保存 各部分之间的通信方式如下。 View 传送指令到 Controller Controller 完成业务逻辑后,要求 Model 改变状态 Model 将新的数据发送到 Vie

YCM1101743158的博客 2666

ViewModel和MVP中的Presenter结合使用

ViewModel的简单使用,前面文章已经有提过,这里结合MVP一起使用,达到更高的解耦效果。定义ViewModel,Presenter中进行Model数据的访问,这里借助GreenDao对Sqlite进行数据库操作,如果是本地数据,直接写一个方法获取本地数据即可,Activity中实现数据的绑定和观察,借助LiveData变量的 setValue() 方法将 Presenter中获取到的Model数据赋值给ViewModel中的LiveData变量

曲幽 630
上一篇: YSpinner
Yann_zhao
博客等级 码龄10年 3粉丝 3原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值