README.md

    2020年最新最实用的android-MVVM框架



    注册的密码规则是数字加字母超过8位即可 测试账号:13126965106 密码:111111aa

    阅读此文档前,先尝试运行项目,文档中部分类名需要结合项目中代码进行参考和理解

    一、业务

    1. 功能:

    • 登录注册(跳转主页后关闭,已登录用户可直接进入主页);
    • 仿微信朋友圈,Recyclerview嵌套RecyclerView实现多图布局列表切换(一张横向全屏,二张横向全屏,三张横向全屏,四张分两行且横向全屏);
    • 发表朋友圈回传值刷新(viewmodel中livedata妙用);
    • 多图带参数上传;
    • 首页和设置页分别退出登录(intent的flag使用);

    二、技术及场景

    1. 技术要点:

    • ViewModel在xml页面变量同一命名"vm",Activity和Fragment中使用ViewModel有明显的区别,请认真仿照;
    • item的xml被多个Adapter使用,而且model数据(bean)不一致的情况,切勿盲目binding.setVariable设置进行单向页面绑定,请在adapter中手动控件赋值,不要xml-binding;
    • Adapter中复杂控件处理需要大对象,建议灵活使用binding寄存,参见CircleAdapter类
    • ObjectBox快速实现对象存取
    • LiveData对网络请求数据灵活设置,view层基于观察者模式填充
    • viewbinding中onClick,onCheckedChanged等事件使用,其他事件根据Listenter实现方法的名字举一反三
    • conf.gradle对于版本和打包管理,做到清晰-快速的进行组件调试;common包中build.gradle中尽量容纳整个工程所需要的第三方框架/SDK的版本,方便所有模块使用和调试,建议小组主程/架构的同学管理
    • Fragment拆分组件之后的通信方案,参照下方mvvm-v3.1介绍
    • 项目最低兼容4.0.3,因为objectbox最低支持这个版本

    2. 期望拥有的能力(待完成):

    2.1 2020.12.01(待完成,可预见的能够帮助工程变强大的工作)

    • 调试模式:应用配置项参数等调试项修改和查看,需要IOC和持久化等支持。
    • 组件感知能力:在已经打包的apk包中进入调试模式,可查看到组件的版本和已包含或未包含的必要组件。
    • 组件版本冲突打包能力:单个组件不同版本都可以参与打包,且安装之后正常运行,能够查看单个组件多个版本,支持本地进行版本切换。

    3. 使用的开源框架:

    • androidx:这个系列的jar包和appcompat.support对立的,参见谷歌官方文档
    • lifecycle-viewmodel+livedata+DataBinding: 生命周期管理,完全解耦,方便系统内存管理释放,基于观察者模式实现数据更新等等
    • Retrofit2:感谢Square公司
    • rxjava2:感谢ReactiveX,突然发现Rxjava已经发布3.0了
    • ObjectBox:android上运行速度最快的数据库,基于c/c++开发,native接口
    • banner:banner如果不需要就去掉。
    • Fresco:感谢FaceBook,另外给大家提个醒, Fresco有自己的内存回收机制,但是这个回收阈值没有设置,请自行百度解决,提示:Fresco eviction哈哈哈
    • XRecyclerView
    • RxPermissions:权限申请比较好用
    • Arouter:感谢阿里巴巴技术团队
    • BoostMultiDex:感谢头条技术团队抖音多dex加载方案

    三、分支更新日志(倒叙)

    8.master 2020.12.01

    • 更换LogUtils为logger;方便日志查找,为后续日志同步服务器/文件记录提供基础;
    • Fragment的伪ViewModel依托所属Activity-LifeCycleOwner实现生命周期感知;具体实现请查看WDFragViewModel使用;

    7.master 2020.09.13

    • 对于ObjectBox一些建议
      1. 大小限制:ObjectBox默认最大为1GB,当db文件达到1G,新增数据会报出SQL异常,可通过maxSizeInKByte()改变最大限制,建议同SQLite一样,设置为磁盘大小,使用其他方法在部分业务上做磁盘大小检测,磁盘不足及时预警;另外从插入1条-100W条数据来看,ObjectBox扩容基本上从SQlite原生数据库几十倍降低到2.5倍左右;
      2. 经过测试,在插入速度方面有以下几个建议:
        • ObjectBox相比于原生Sqlite在批量插入数据方面速度快很多,而且使用put(list or obj...)都是自动开启事务;反之Sqlite对于单条多频次数据入库在速度上远远超过ObjectBox;
        • 业务角度出发,如果是单条多频次bean对象插入明显Sqlite占优,ObjectBox执行速度有所下降,这种场景下可以考虑队列的方式做批量插入;
      3. 经过测试,在查询速度方面有以下建议:
        • 主键ID查询单条数据在百万级数据中Sqlite稍优;在单表条件查询之下,数据量上万情况下,Objectbox过于优秀。
      4. 在删除数据方面,由于都是Sqlite数据库,所以删除只是删数据,并不会减小磁盘内存,如果要缩小db大小,可以自行设计方案;
      注:①测试使用小米9手机,单表数据量从最小100条到最大200W条,字段为30个String+一个自增ID,每个字符串长度都在20到30长度的随机字符,测试过程没有严格做到控制变量法,所以测试并不是很严谨,仅供参考;
      ②我们项目使用sqlite最近碰到SQLiteDatabaseCorruptException: database disk image is malformed等一系列的数据库损坏bug(官方说明关机或sd卡打满可能出现),我们线上用户不到万一的概率,从大数据定位出是几个深度用户,
      解决这个问题的最好方式是引入腾讯wcdb中的c++的repair模块修复损坏数据库,构建新库,UI层做友好提示(类似于QQ更新之后跳出的加载数据页面),工作量比较大,但实际效果比较好,修复数据有利于用户留存;

    6.master 2020.09.05

    • 新增scope插件,在gct文件夹中,这是一个idea插件,需要打开idea/studio进行plugin插件安装,安装之后会生成两个入口,1.VCS提交面板commit message增加小文本按钮;2.idea/studio面板增加VVScopeTree树形结构面板;插件作用是为了标准化commit message文案,规范每一次commit message的描述。
    • scope插件是什么呢?怎么使用?
      1. 参见这位外国大兄弟:https://github.com/MobileTribe/commit-template-idea-plugin.git
      2. 在此基础上,根据公司项目情况,我又开发了Tree树形结构功能,安装插件之后,会在idea或studio主页上增加一个VVScopeTree,方便所有模块业务进行管理。
      注:在Version Control中commit弹框,输入message使用插件编辑;

    5.master 2020.08.09

    • 首页UI结构更新:MainActivity使用FragmentManager的add hide show;MainFromViewPagerActivity使用ViewPager+Fragment;使用的时候只需要注释或者放开@Router注解即可

    对于组件aar版本的说明
    前提/背景/须知:
    目前此工程可以满足大家开发需要,但随着项目上线,组件越来越多,小组成员不断增多,我们整体工程越来越大,所以我们期望一个工程只包含两部分:app壳工程+自己负责的组件,对于自己不负责的组件只需要在壳工程中引入依赖即可。 需要承认一点,现在包括之前的版本都没有做到组件开发和维护的灵活性,所以最近有时间会继续改进一版,做到一个工程只包含两部分:app壳工程+自己负责的组件; 使用了现在或以前版本的小伙伴也不要伤心,组件改进不涉及任何业务功能,所以你依旧可以根据下方提供的技术方案对自己的项目改进。

    技术方案流程:

    1. 建议大家一步到位,不要本地打包拷贝libs,请自行搭建公司私有仓库(本地或者远程服务器均可),然后配置gradle发布脚本,发布aar到私服上;
    2. 请主程/小组长在app的build.gradle中dependencies引入所有的aar,在config.gradle做好aar版本管理,视情况删除工程中build.gradle的打包流程(可保留,应对后续组件功能扩展);
    3. 将整理好的工程clone多份,删除.git,在settings.gradle中删除不需要的组件名称,然后在每份源码中保留不同的组件,重新上传仓库,完成改版。

    关于工具类改进的一些想法:
    考虑了很多次是否改进,最终个人决定不改进,留给各位小伙伴完成,目前common中util工具类比较少,而且只使用了其中的某几个,大家可以根据需求自行增加, 另外比较重要的Log/File工具类强烈建议根据业务和Android版本做深度改进,推荐大家在github中搜索一下相关的工具类工程。

    4. mvvm-v3.1 2020.06.12

    • Fragment组件化通信怎么实现的,实现原理?

      1. 使用组合设计模式,ViewModel(以下简称VM)必须和Activity放在同一个模块,Fragement必须继承WDFragment,因为其中使用自定义FragViewModel(以下简称FVM)抽象类(这个类没有继承VM,是自定义的一个抽象类);
      2. Activity中通过Arouter获取其他组件中的Fragment,然后通过此Fragment的方法拿到其绑定的FVM,然后将Activity的VM中LiveData变量传递给FVM,从而实现了数据共享。
    • 我怎么快速使用Fragment组件化通信?

      1. 打开open_user组件,找到UserViewModel类,打开布局文件frag_me.xml,找到dataShare方法,即可快速了解并使用。

    组合设计模式(Component),通过对子节点初始化赋值,利用MutableLiveData达到共享数据的目的,建议使用Message对象,减少代码量,增加功能最大适配性。

    • Arouter中path是常量字符串,当模块众多的时候,需要实现path共享。

      1. 新增常量生成插件,VcStrong自己开发的,放到了jitpack.io上,根据module的build.gradle配置constant动态生成常量类。
      2. 目前支持自定义项目名,报名,类名生成常量类,常量参数生成的时候默认使用追加策略(不是覆盖哦)
    • 如何使用常量插件呢?

    在工程的build.gradle中dependencies添加:
    classpath 'com.github.VcStrong:ConstantPlugin:0.0.1'
    在module的build.gradle中使用:
    apply plugin: 'com.vc.constant'//启用常量插件
    constant {
        enable false//不进行编译,不写的话,默认每次都进行编译,查看build日志
        moduleName "common"//生成新代码存放的moduleName
        packageName "com.vc.wd.common.util"//生成的新代码放在哪个包下
        className "Constant"//生成的常量类名
        fieldMap = [
            ACTIVITY_URL_MAIN : '/main/MainActivity',
            ACTIVITY_URL_ADD_CIRCLE : '/main/AddCircleActivity'
        ]//属性参数
    }
    • 常量插件使用都有哪些场景呢?
      1. Arouter多模块之间path常量共享;
      2. Intent隐式跳转action/data共享问题;
      3. 只要你需要生成常量类,都可以灵活使用。

    3.mvvm-v3 追风中。

    v3版本绝对让你眼前一新,重新提起兴致,追求适配到4.x,由于ObjectBox框架最低支持4.0.3,所以本项目最低只能支持4.0.3版本机型, 新增功能处处都能体现代码的奇妙:

    • 重新定义config.gradle中常量:分为SDK_VERSION(不因发布分支改变的常量)和active(跟分支相关的参数)。 这么做出于对项目在不同阶段不同部门的打包的时候,部分参数需要进行调整,例如:推送key,包名,域名,项目名等; 主要目的提升研发-测试-运维运营等部门沟通协作;
    • 新增今日头条-抖音团队multidex打包,适配4.x平台加载dex问题,详细请参照WDApplication代码;
    • 拆分请求接口,放到各个相关module中,开发阶段尽量减少多人操作common包。

    2.mvvm-v2 质量的提高来自不断地追求

    v2版本在v1基础上进行组件化升级,由于对组件和模块的概念有了更深的了解,参考了网上的组件化教程,实践总结利弊之后,决定自己写一套优秀高效率的组件运行gradle:

    • 公司场景:多模块业务联调,统一运行;
    • 此demo种组件化打包好处:根据gradle配置动态改变模块的引入,分分钟能解决一个模块或者多个模块打包联调;
    • 具体方式如下:
      1. 项目根目录新建了config.gradle存放系统变量;
      2. 项目根目录新建了module.gradle存放业务module中build.gradle公用参数,common和app不建议引入(部分重要配置必须写在这两个module中);
      3. 项目根目录build.gradle使用groovy动态改变app(module)对模块的引入;
      4. 所有选中的模块可根据自己要求,决定是否需要改变AndroidManifest.xml的引入,仿照open_main模块中的sourceSets;
      5. 支持多个Module—Application共存,方便处理推送,IM等组件初始化问题

    注:请认真查看config.gradle中的变量备注

    1.mvvm-v1 2020.04.20

    这是一个整合架构,所有功能开发都只能在一个module中

    项目简介

    🚀 Github 镜像仓库 🚀

    源项目地址

    https://github.com/VcStrong/JetpackMVVM

    发行版本

    当前项目没有发行版本

    贡献者 2

    D dingtaotao @dingtaotao
    V VcStrong @VcStrong

    开发语言

    • Java 100.0 %