乐趣区

关于mvvm:彻底理解Android架构重构Jetpack-MVVM

前言

汇聚了业界出名架构文章。从建筑学的常识中失去一些对架构的思考,并以架构设计准则和目标对 Jetpack MVVM 从新结构!github 后续本我的项目将继续更新,并欠缺 wanAndorid 的所有性能。还会用 23 种设计模式在我的项目中实际,彻底了解设计模式在业务场景中的应用,欢送关注

Github:https://github.com/blindmonk/WanArchitecture

一、什么是架构

1.1 架构介绍

架构到底是什么?如何更好的了解架构。咱们晓得中国文字博大精深能够说从文字的组成就能了解其含意。架构也不例外“架构”是由“架”、“构”组成。

架:建造、搭设、撑持。简称:整体构造 构:屋宇、供人寓居的木、砖瓦构筑物。简称:组件

整体构造和组件的组合就造成了架构。以 Android 架构为例子一个 APP 通常是有 class(类)组成,而这些 class 之间如何如何组合、相互之间如何产生作用,则是影响这个 APP 自身的关键点。细分的话能够分为类、接口(连接器)、工作流。所谓类就是组成架构的外围“砖瓦”,而接口则是这些类之间通信的门路、通信的机制、通信的冀望后果。工作流则是形容零碎如何应用类和接口实现某一项需要比方:一次网络申请。下面介绍架构中提到了屋宇、木头、砖瓦可见架构和修建有着彼此的分割。

1.2 建筑学

上世纪 60 年代曾经设计软件架构这个概念了,到了 90 年代软件架构这个概念才开始流行起来。而计算机的历史开始于上世纪五十年代相比修建历史就十分短暂了,建筑工程从石器时代就开始了。人类在几千年的建筑设计实际中积攒了大量的教训和教训,建筑设计基本上蕴含两点,一是建筑风格,二是修建模式。独特的建筑风格和失当抉择的修建模式,能够使它成为一个举世无双的修建。

下图的照片显示了现代玛雅修建:Chichen-Itza,九个微小的石级堆垒而上,九十一级台阶(象征着四季的天数)夺路而出,塔顶的神殿耸入云天。所有的数字都如日历般谨严,格调雄浑。难以想象这是石器时代的建筑物。

英国首相丘吉尔说,咱们结构建筑物,修建也结构咱们,英国下议院的会议厅较狭隘,无奈使所有的下议院议员面向同一个方向入座,而必须分成两侧入座。丘吉尔认为,议员们入座的时候天然会抉择与本人政见雷同的人同时入座,而这就是英国政党制的起源。

二、架构设计目标

简直所有的软件设计理念都能够在浩瀚的建筑学历史中找到。许多人认为“模式必须遵从性能”(你认同这种观点吗?欢送在评论区留下你的认识)。而好的设计既有模式又有性能。比方咱们的北京大兴国内机场大兴机场以航站楼为外围向周围延展从地面鸟瞰就像是一只展翅欲飞的凤凰,以航站楼核心区为核心,别离向西南、西北、中南、东北、东南五个方向伸出了五条指廊,通往北京大兴国内机场的飞行区。这种从核心向五湖四海延长的设计,使航站楼中心点到最远端登机口的间隔只有 600 米左右,旅客步行返回最多只需 8 分钟。

修建的设计又有肯定的目的性,而软件架构设计也同理。软件架构目的性大抵可分为可扩展性、可定制化、可伸缩、可维护性:

1. 可扩展性 APP 必须可能在用户的 UV/PV 数量疾速减少的状况下,放弃软件正当的性能。只有这样在疾速的从 0 到 1 的需要迭代中能力后顾无忧。

2. 可定制化: 在同一个软件系统中可能面向的用户群体是不同的、多样的,须要满足依据用户群的不同和市场需求的不同进行定制化。比方一个 APP 中某些性能只针对特定用户凋谢。

3. 可伸缩性: 在新技术呈现的时候,一个软件系统该当容许接入新技术,从而对现有零碎进行性能和性能的扩大。

4. 可维护性: 软件系统的保护包含两方面,一是修复现有的 bug,二是将新的迭代需要开发到现有零碎中去。一个易于保护的零碎能够无效地升高人力和物力。

三、实际一个 APP:玩 Android

针对上面对架构的介绍,置信曾经从生疏走向相熟了。然而最重要的还是实际,平凡的毛主席已经说过 你要想晓得梨子的味道,就要亲口尝一下。因而借用了 wanAndoird 凋谢 API 简略实现一个 APP 并概括上述架构的关键点,次要的性能点如下:

  • 首页是热搜文章的分类列表
  • 我的项目页面次要包含残缺我的项目
  • 文章、我的项目点击能够查看详情

不晓得还有没有印象上文提到了架构“模式必须遵从性能”当然这不是权威的定义,能够作为参考。咱们先不论是模式遵从性能还是性能遵从模式,能够结构化思维了解下这句话,架构大抵可分为:模式、性能所以咱们顺次依照此两点进行搭建 wanAndroid 我的项目。

3.1 架构 – 模式

从模式自身而言包含两局部。一是事物外在的形态,二是外在的构造、组合形式。实际上,这两者为同一。内容如何外在组合,对外就天然有某种体现的形态。

咱们关上我的项目的第一眼接触到和看到的就是咱们我的项目的目录构造,更清晰更简洁的目录构造能够使咱们更快的上手我的项目。这里次要分为两局部外围模块、业务功能模块:

外围模块次要有以下职责:

  • Dagger 依赖注入解决。
  • 扩大性能:各种 utils。
  • 根底层的形象:BaseActivity、BaseViewModel 等
  • 第三库解决、网络异样解决等

业务功能模块次要有以下益处:

  • 高内聚性
  • 清晰的性能构造
  • 模块化
  • 性能隔离并封装

在主 APP 下进行了 corefeatures 的划分,业务模块并没有依照模块化的模式进行多 moudle 拆分而是聚合在 features 下,以包的模式进行了聚合,这样做的益处如下:

  • 更快的编译速度
  • 缩小 maven 库的依赖抵触
  • 通用性能的重用性
  • 包的内聚力

能够看到咱们并没有采纳依照业务 module 进行模块化划分,因为我之前接触过一个我的项目拆分了 40 多个 module 可想而知我的项目一旦宏大起来害处也就是裸露进去:

  • 编译一次我的项目高达 7/8 分钟,编译速度优化能够 * 看我之前的文章(编译速度优化)
  • 我的项目中的 moudle 依赖犬牙交错

当然我并不拥护多 module 模块化的存在,因为任何模式都有利有弊,这取决于以后的我的项目的业务来抉择应用那种模式。此外我的项目中全副采纳 kotlin 编写:

  • build.gradle.kts .kts 也是官网推崇的能够使 gradle 更加简化
  • buildSrc来解决 gradle 依赖
3.2 架构 – 性能

在玩 Android 中的业务点性能点次要有文章、我的项目获取,而这些性能点大部分都离不开网络申请和回调解决。这里不再形容 MVC、MVP、MVVM 的区别和如何抉择,然而我能够阐明一点是任何架构模式都没有最好、最优,只有最适宜以后业务的才是好架构。 当初 google 官网推崇的架构次要是 MVVM 所有咱们次要说下 MVVM。更具体的能够查看官网文档 利用架构指南:

MVVM 架构模式满足上文咱们形容合乎的架构设计的目标,同时也准守了官网给定的架构准则,架构准则大抵有两点如下。可能光看这两个定义可能不太容易了解。所有咱们用结构化思维的形式了解下,关注点拆散就是将简单问题做正当的合成,再钻研合成的侧面,最初合成整体的解决方案。因而咱们在 Activity 或 Fragment 不应该做业务逻辑而是把性能点拆分成须要最小的最优解,最初合并成整体计划。比方 mvvm 咱们衍生出 ViewModel、LiveData、Model 等。

  • 关注点拆散 Activity 或 Fragment 中的代码应是解决界面和操作系统交互的逻辑应使这些类尽可能放弃精简,这样能够防止许多与生命周期相干的问题。
  • 通过模型驱动界面 模型是负责解决利用数据的组件。它们独立于利用中的 View 对象和利用组件,因而不受利用的生命周期以及相干的关注点的影响

MVVM 中每个组件仅依赖于其下一级的组件如:activity-->viewMoudle-->Repository。这时候你可能有纳闷,如果是单向依赖那网络申请的回调怎么解决?这里引出一个概念“响应式编程”联合 liveData 做解决其外部是观察者模式,并且关联视图的申明周期如:Activity、Fragment 或 Service。应用 LiveData 的益处如下:

  • 不会产生内存透露 观察者会绑定到 Lifecycle 对象,并在其关联的生命周期受到销毁后进行自我清理。
  • 不会因 Activity 进行而导致解体 如果观察者的生命周期处于非沉闷状态(如返回栈中的 Activity),则它不会接管任何 LiveData 事件。
  • 不再须要手动解决生命周期 界面组件只是察看相干数据,不会进行或复原察看。LiveData 将主动治理所有这些操作,因为它在察看时能够感知相干的生命周期状态变动。
3.3 UseCase

UseCase 是 Clean 架构中的一个概念,其中次要用于 UI 和数据层的连贯同时也会进行 IO 的切换,这里能够看到本我的项目摈弃了 Rxjava 因为他齐全能够用 Kotlin 来代替。

abstract class UseCase<out Type, in Params> where Type : Any {abstract suspend fun run(params: Params): Either<Failure, Type>{operator fun invoke(params: Params, onResult: (Either<Failure, Type>) -> Unit = {}) {val job = GlobalScope.async(Dispatchers.IO) {run(params) }
      GlobalScope.launch(Dispatchers.Main) {onResult(job.await()) }
  }

  class None
}
3.4 一个残缺网络申请流程

  • View:一个网络申请的发送并订阅,解决 UI 数据。
  • ViewModel:为 View(Activity/Fragment) 提供数据,并解决业务逻辑。
  • LiveData:具备生命周期可察看的数据存储器类,LiveData 存储在 ViewModel 中
  • UseCases:用于连贯 ViewModel 和 Model,并更新 LiveData。
  • Model:能够从网络、数据库或其余 API 获取数据

四、总结

咱们能够领会到从架构实践定义到实际的过程置信你有了本人的了解和见解,但这只是一种实现形式,如果在满足架构设计目标和架构准则的状况下你有更好的实际形式或者有任何和架构我的项目的疑难点都可迎在评论区或者 Github 中留言探讨。这里我也有个疑难点就你认同模式必须遵从性能?欢送留下你的见解。

后续本我的项目将继续更新,并欠缺 wanAndorid 的所有性能。还会用 23 种设计模式在我的项目中实际,彻底了解设计模式在业务场景中的应用,欢送继续关注。当其余的平台如后端、前端架构的搭建都是必由之路的。然而我还是有几点倡议:

  • 业务决定架构
  • 不要适度设计
  • 面向接口编程
  • 模式需遵从性能
参考文献:

利用架构指南、CleanArchitecture、LiveData 概览

退出移动版