前言

上篇文章我给大家分享了我对Android架构的了解,从思维层面去讲述架构的演进过程。很多小伙伴读完后拍手叫好,示意还想听我讲一下对Jetpack 架构的认识 ,本着帮人帮到底的精力,明天我将再次动笔 尽量从实质上讲清楚Jetpack 架构存在的意义,以及解决的问题。

同时我也有一个基于Jetpack MVVM的残缺开源我的项目,曾经依照上篇文章提出的思维做了重构,目前托管在Github,心愿也能为你提供一些帮忙。github地址

常识储备:须要对Lifcycle、LiveData、ViewModel、DataBinding有根本理解

目录

  • 1. 有了Lifecycle,再也不必放心生命周期同步问题

    • 1.1 为什么要做生命周期绑定?
    • 1.2 Lifecycle解决了哪些问题?
  • 2. LiveData并不是只使用观察者模式

    • 2.1 观察者模式的长处有哪些?
    • 2.2 LiveData基于观察者模式又做了哪些扩大?
    • 2.3 LiveData + Lifecycle 实现 1 + 1 > 2
  • 3. ViewModel与LiveData真乃天作之合

    • 3.1 如何优雅的实现Fragment之间通信?
    • 3.2 由ViewModel负责 VM/Presenter 的益处有哪些?
  • 4. 解除你对DataBinding的误会

    • 4.1 应用DataBinding的益处有哪些?
    • 4.2 为什么很多人说DataBinding很难调试?
  • 5. Jetpack和MVVM有什么关系?

    • 5.1 什么是MVVM
    • 5.2 Jetpack只是让MVVM更简略、更平安

1. 有了Lifecycle,再也不必放心生命周期同步问题

1.1 为什么要做生命周期绑定?

对于Activity/Fragment其最重要的概念就是生命周期治理,咱们开发者须要在不同生命周期回调中做不同事件。比方onCreate做一些初始化操作,onResume做一些复原操作等等等等,以上这些操作都比拟繁多间接去写也没有多大问题。

但有一些组件须要强依赖于Activity/Fragment生命周期,惯例写法一旦忽略便会引发平安问题,比方上面这个案例:

现有一个视频播放界面,咱们须要做到当跳到另一个界面就暂停播放,返回后再持续播放,退出后重置播放,惯例思路:

#class PlayerActivity    onCreate(){        player.init()    }    onResume(){        player.resume()    }    onPause(){        player.pause()    }    onDestroy(){        player.release()    }

读过我上篇文章的小伙伴可能一眼就能看进去这违反了管制反转,人不是机器很容易写错或者忘写,特地是player.release()如果忘写便会引发内存透露 此时咱们能够基于管制反转思维(将player生命周期控制权交给不会出错的框架)进行革新: 第一步:

interface ObserverLifecycle{    onCreate()    ...    onDestroy()}

首先定义一个观察者接口,蕴含Activity/Fragment次要生命周期办法

第二步:

class BaseActivity{    val observers = mutableList<ObserverLifecycle>()    onCreate(){        observers.forEach{            observer.onCreate()        }    }    ...    onDestroy(){        observers.forEach{            observer.onDestroy()        }    }}

BaseActivity中察看生命周期并逐个告诉到observers的观察者

第三步:

class VideoPlayer : ObserverLifecycle{    onCreate(){        init()    }    ...    onDestroy(){        release()    }}class PlayerActivity : BaseActivity{    observers.add(videoPlayer)}

播放器实现ObserverLifecycle接口,并在每个机会调用相应办法。PlayerActivity只需将videoPlayer注册到observers即可实现生命周期同步。

其实不光videoPlayer,任何须要依赖Activity生命周期的组件 只需实现ObserverLifecycle接口最初注册到Activityobservers即可实现生命周期自动化治理,进而能够躲避误操作带来的危险

1.2 Lifecycle解决了哪些问题?

既然生命周期的同步如此重要,Google必定不会熟视无睹,尽管自定义ObserverLifecycle能够解决这种问题,但并不是每个人都能想到。所以Google就制订了一个标准化的生命周期管理工具Lifecycle,让开发者碰到生命周期问题自然而然的想到Lifecycle,就如同想在Android手机上新建一个界面就会想到Activity一样。

同时ActivityFragment外部均内置了Lifecycle,应用非常简单,以1.1 案例通过Lifecycle革新后如下:

class VideoPlayer : LifecycleObserver {    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)    fun onCreate(){        init()    }    ..    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)    fun onDestroy(){        release()    }}class PlayerActivity : BaseActivity{    lifecycle.addObserver(videoPlayer)}

两步操作即可,不必咱们本人向观察者(videoPlayer)做生命周期散发解决。

2. LiveData并不是只使用观察者模式

2.1 观察者模式的长处有哪些?

观察者是一种常见并且十分实用的一种行为型模式,具备扩展性强、耦合性低的个性。

本文1.1 中 生命周期同步设计就是一个规范的观察者模式,ObserverLifecycle可作为观察者,PlayerActivity作为被观察者,当被观察者(PlayerActivity)生命周期产生扭转时会被动告诉到观察者(VideoPlayer)

同时观察者在不扭转代码构造的状况随便扩大,比方PlayerActivity属于一个MVP架构,此时能够将Presenter实现ObserverLifecycle作为观察者 随后 注册到被观察者(PlayerActivity)中, 这样Presenter也能够监测到Activity生命周期,并且代码构造没有任何扭转,合乎开闭准则(对扩大开发 批改敞开)

2.2 LiveData基于观察者模式又做了哪些扩大?

LiveData符合标准的观察者模式,所以它具备扩展性强、耦合性低的个性,同样它还是一个存储数据的容器,当容器数据扭转时会触发观察者,即数据驱动。

数据驱动是前端开发畛域十分重要的一个概念,说数据驱动之前咱们先思考一个问题,为什么要扭转数据? 答案不言而喻,无非是想让数据使用者感知到而已,而LiveData能够优雅的实现这一流程,将 扭转、告诉 两步操作合并为一步 即省事也进步了安全性.

依据LiveData的个性决定它非常适合去做数据驱动UI,上面举个例子简略形容下:

# 需要:扭转textView内容以及对应的数据,用LiveData实现形式如下val liveData = MutableLiveData<String>()liveData?.observe(this, Observer { value->            textView.text = value        })//这一步会扭转liveData值并且会触发textView从新渲染liveData.value = "android"

看起来平平无奇甚至天经地义,但它的确解决了咱们前端开发的痛点,在此之前数据和UI都须要咱们开发者独自批改,当面对十几个View时很难做到不漏不忘。 引入liveData后扭转数据会主动触发UI渲染,将两步操作合并为一步,大大降低出错的概率 对于数据驱动UI上篇文章我曾经做了详细描述,感兴趣的能够翻回去查看。

2.3 LiveData + Lifecycle 实现 1 + 1 > 2

LiveDataLifecycle的加持下能够实现只在可见状态接管告诉,说的艰深一点Activity执行了onStop()后外部的LiveData就无奈收到告诉,这样设计有什么益处? 举个例子: ActivityAActivityB共享同一个LiveData,伪代码如下

class ActivityA{    liveData?.observe(this, Observer { value->            textView.text = value        })}class ActivityB{    liveData?.observe(this, Observer { value->            textView.text = value        })}

ActivityA启动ActivityB后屡次扭转liveData值,等回到ActivityA时 你必定不心愿Observer收到屡次告诉而引发textView屡次重绘。

引入Lifecycle后这个问题便可迎刃而解,liveData绑定Lifecycle(例子中的this)后,当回到ActivityA时只会取liveData最新的值而后做告诉,从而防止多余的操作引发的性能问题

3. ViewModel与LiveData真乃天作之合

3.1 Jetpack ViewModel 并不等价于 MVVM ViewModel

常常有小伙伴将Jetpack ViewModelMVVM ViewModel等量齐观,其实这二者基本没有在同一个档次,MVVM ViewModelMVVM架构中的一个角色,看不见摸不着只是一种思维。 而Jetpack ViewModel是一个实实在在的框架用于做状态托管,有对应的作用域可追随Activity/Fragment生命周期,但这种个性恰好能够充当MVVM ViewModel的角色,分隔数据层和视图层并做数据托管。

所以论断是Jetpack ViewModel能够充当MVVM ViewModel 但二者并不等价

3.2 如何优雅的实现Fragment之间通信?

ViewModel官网定义是一个带作用域的状态托管框架,可通过指定作用域和Activity/Fragment共存亡,为了将其状态托管施展到极致,Google甚至独自为ViewModel开了个后门,Activity横竖屏切换时不会销毁对应的ViewModel,为的就是横竖屏能共用同一个ViewModel,从而保证数据的一致性。

既然是状态托管框架那ViewModel的第一要务 就要时时刻刻保障最新状态散发到视图层,这让我不禁想到了LiveData,数据的承载以及散发交给Livedata,而ViewModel专一于托管LiveData保障不失落,二者搭配几乎是天作之合。

有了ViewModelLiveDataFragment之间能够更优雅的通信。比方我的开源我的项目中的音乐播放器(属于单Activity多Fragment架构),播放页和首页悬浮都蕴含音乐根本信息,如下图所示:

想要使两个Fragment中播放信息实时同步,最优雅的形式是将播放状态托管在Activity作用域下ViewModelLiveData中,而后各自做状态监听,这样只有要有一方扭转就能立刻告诉到另一方,简略又平安,具体细节可至我的开源我的项目中查看。

3.3 由ViewModel负责 VM/Presenter 的益处有哪些?

传统MVVMMVP遇到最多的的问题无非就是多线程下的内存泄露,ViewModel能够齐全躲避这个问题,外部的viewModelScope是一个协程的扩大函数,viewModelScope生命周期追随ViewModel对应的Lifecycle(Activity/Fragment),当页面销毁时会一并完结viewModelScope协程作用域,所以将耗时操作间接放在viewModelScope即刻

另外在界面销毁时会调用ViewModelonClear办法,能够在该办法做一些开释资源的操作,进一步升高内存泄露的危险

4. 解除你对DataBinding的误会

4.1 应用DataBinding的作用有哪些?

DataBinding最大的长处跟惟一的作用就是数据 UI双向绑定UI和数据批改任何一方另外一方都会主动同步,这样的益处其实跟LiveData的相似,都是做数据跟UI同步操作,用来保证数据和UI一致性。其实写到这能够发现,不论是LiveDataDataBinding还是DiffUtil都是用来解决数据和UI一致性问题,可见Google对这方面有如许器重,所以咱们肯定要紧跟官网步调

小知识点:

DataBinding包中的ObservableField作用跟LiveData基本一致,但ObservableField有一个去重的成果,

4.2 为什么很多人说DataBinding很难调试?

常常听一些小伙伴提DataBinding不好用,起因是要在xml中写业务逻辑不好调试,对于这个观点我是持否定态度的。并不是我批准xml中写业务逻辑这一观点,我感觉碰到问题就得去解决问题,如果解决问题的路上有阻碍就尽量扫清阻碍,而不是一味的回避。

{vm.isShow ? View.VISIBLE : View.GONE}之类的业务逻辑不写在xml放在哪好呢?对于这个问题我在上篇文章Data Mapper章节中形容的很分明,拿到后端数据转换老本地模型(此过程会编写所有数据相干逻辑),本地模型与设计图一一对应,岂但能够将视图与后段隔离,而且能够解决xml中编写业务逻辑的问题。

5. Jetpack和MVVM有什么关系?

5.1 什么是MVVM

MVVM其实是前端畛域一个专一于界面开发的架构模式,总共分为ViewViewModelRepository三个模块 (需严格依照繁多设计准则划分)

  • View(视图层): 专门做视图渲染以及UI逻辑的解决
  • Repository(近程): 代表近程仓库,从Repository取须要的数据
  • ViewModel: Repository取出的数据需暂存到ViewModel,同时将数据映射到视图层

分层诚然重要,但MVVM最外围点是通过ViewModel做数据驱动UI以及双向绑定的操作用来解决数据/UI的一致性问题。MVVM就这么些货色,千万不要把它了解的特地简单

双向绑定和单向驱动应该如何抉择?

当面临TextView之类的View单向驱动曾经齐全够用了,毕竟在咱们的认知里是不须要通过TextView显示的文案扭转对应数据的,此时单向驱动就能保障数据、UI统一。 而双向绑定通常用在可交互式的View中,比方EditText内容会通过用户输出而扭转的,此时须要通过双向绑定能力保障数据、UI统一。不论是双向绑定还是单向驱动,只有能保障数据、UI统一,那它就合乎MVVM思维

其实我上篇文章也简略说过,好的架构不应该局限到某一种模式(MVC/MVP/MVVM)上,须要依据本人我的项目的理论状况一直添砖加瓦。如果你们的后端比拟善变我倡议引入Data Mapper的概念~如果你常常和共事开发同一个界面,能够试图将每一条业务逻辑封装到use case中,这样大概率能够解决Git抵触的问题..等等等等,总之只有能实实在在 进步 开发效率以及我的项目稳定性的架构就是好架构.

5.2 Jetpack只是让MVVM更简略、更平安

Jetpack是Android官网为确立标准化开发而提供的一套框架,Lifecycle能够让开发者不必过多思考 生命周期引发的一系列问题 ~ 有了DataBinding的反对让数据UI双向绑定成为了可能 ~ LiveData的存在解除ViewModelActivity双向依赖的问题....

归根到底Jetpack就是一套开发框架,MVVM在这套框架的加持之下变得更加简略、平安。

Tips:作者公司我的项目引入Jetpack后,我的项目稳定性有着肉眼可见的晋升。

综上所述

  • Lifecycle 解决了生命周期 同步问题
  • LiveData 实现了真正的状态驱动
  • ViewModel 能够让 Fragment 通信变得更优雅
  • DataBinding 让双向绑定成为了可能
  • Jetpack 只是让 MVVM 更简略、更平安

相干视频举荐:

【2021最新版】Android studio装置教程+Android(安卓)零基础教程视频(适宜Android 0根底,Android初学入门)含音视频_哔哩哔哩_bilibili

Android架构设计原理与实战——Jetpack联合MVP组合利用开发一个优良的APP!_哔哩哔哩_bilibili

Android进阶必学:jetpack架构组件—Navigation_哔哩哔哩_bilibili

Android进阶零碎学习——Jetpack先天优良的基因能够防止数据内存透露_哔哩哔哩_bilibili

本文转自 https://juejin.cn/post/6955491901265051661,如有侵权,请分割删除。