精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

MVI 架構更佳實踐:支持 LiveData 屬性監聽

開發 架構
本文主要介紹如何通過監聽LiveData的屬性,來實現MVI架構下的局部刷新。

前言

前面我們介紹了MVI架構的基本原理與使用:MVVM 進階版:MVI 架構了解一下~

MVI架構為了解決MVVM在邏輯復雜時需要寫多個LiveData(可變+不可變)的問題,使用ViewState對State集中管理,只需要訂閱一個 ViewState 便可獲取頁面的所有狀態。

通過集中管理ViewState,只需對外暴露一個LiveData,解決了MVVM模式下LiveData膨脹的問題。

但頁面的所有狀態都通過一個LiveData來管理,也帶來了一個嚴重的問題,即頁面不支持局部刷新。

雖說如果是RecyclerView可以通過DifferUtil來解決,但畢竟不是所有頁面都是通過RecyclerView寫的,支持DifferUtil也有一定的開發成本。

因此直接使用MVI架構會帶來一定的性能損耗,相信這是很多人不愿意用MVI架構的原因之一。

本文主要介紹如何通過監聽LiveData的屬性,來實現MVI架構下的局部刷新。

Mavericks框架介紹

Mavericks框架是Airbnb開源的一個MVI框架,Mavericks基于Android Jetpack與Kotlin Coroutines, 主要目標是使頁面開發更高效,更容易,更有趣,目前已經在Airbnb的數百個頁面上使用。

下面我們來看下Mavericks是怎么使用的。

// 1. 包含頁面所有狀態的data class
data class CounterState(val count: Int = 0) : MavericksState
// 2.負責處理業務邏輯的ViewModel,易于單元測試
class CounterViewModel(initialState: CounterState) : MavericksViewModel<CounterState>(initialState) {
// 通過setState更新頁面狀態
fun incrementCount() = setState { copy(count = count + 1) }
}
// 3. View層,必須實現MavericksView接口
class CounterFragment : Fragment(R.layout.counter_fragment), MavericksView {
private val viewModel: CounterViewModel by fragmentViewModel()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
counterText.setOnClickListener {
viewModel.incrementCount()
}
}
//4. 頁面刷新回調,每當狀態刷新時會回調這里
override fun invalidate() = withState(viewModel) { state ->
counterText.text = "Count: ${state.count}"
}
}

如上所示,看上去也很簡單,主要包括幾個模塊:

  1. 包括頁面所有狀態的Model層,其中的狀態全都是不可變的,并且有默認值。
  2. 負責處理業務邏輯的ViewModel,在其中通過setState來更新頁面狀態。
  3. View層,必須實現MavericksView接口,每當狀態刷新時都會回調invalidate函數,在這里渲染UI。

可以看出,Mavericks中View層與Model層的交互,也并沒有包裝成Action,而是直接暴露的方法。

上篇文章也的確有很多同學說使用Action交互比較麻煩,看起來Action這層的確可要可不要,Airbnb也沒有使用,主要看個人開發習慣吧。

支持局部刷新

上面介紹了Mavericks的簡單使用,下面我們來看下Mavericks是怎么實現局部刷新的 。

data class UserState(
val score: Int = 0,
val previousHighScore: Int = 150,
val livesLeft: Int = 99,
) : MavericksState {
val pointsUntilHighScore = (previousHighScore - score).coerceAtLeast(0)
val isHighScore = score >= previousHighScore
}
class CounterFragment : Fragment(R.layout.counter_fragment), MavericksView {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
//直接監聽State的屬性,并且支持設置監聽模式
viewModel.onEach(UserState::pointsUntilHighScore,deliveryMode = uniqueOnly()) {
//..
}
viewModel.onEach(UserState::score) {
//...
}
}
}

  1. 如上所示,Mavericks可以只監聽State的其中一個屬性來實現局部刷新,只有當這個屬性發生變化時才觸發回調。
  2. onEach也可以設置監聽模式,主要是為了防止數據倒灌,例如Toast這些只需要彈一次,頁面重建時不應該恢復的狀態,就適合使用uniqueOnly的監聽模式。

Mavericks實現屬性監聽的原理也很簡單,我們一起來看下源碼。

fun <VM : MavericksViewModel<S>, S : MavericksState, A> VM._internal1(
owner: LifecycleOwner?,
prop1: KProperty1<S, A>,
deliveryMode: DeliveryMode = RedeliverOnStart,
action: suspend (A) -> Unit
) = stateFlow
// 通過對象取出屬性的值
.map { MavericksTuple1(prop1.get(it)) }
// 值發生變化了才會觸發回調
.distinctUntilChanged()
.resolveSubscription(owner, deliveryMode.appendPropertiesToId(prop1)) { (a) ->
action(a)
}

  1. 主要是通過map將State轉化為它的屬性值。
  2. 通過distinctUntilChanged方法開啟防抖,相同的值不會回調,只有值修改了才會回調。
  3. 需要注意的是因為使用了KProperty1,因此State的承載數據類必須避免混淆。

如上,就是Mavericks的基本介紹,想了解更多的同學可參考:https://github.com/airbnb/mavericks。

LiveData實現屬性監聽

上面介紹了Mavericks是怎么實現局部刷新的,但直接使用它主要有兩個問題。

  1. 接入起來略微有點麻煩,例如Fragment必須實現MavericksView,有一定接入成本。
  2. Mavericks的局部刷新是通過Flow實現的,但相信大多數人用的還是LiveData,有一定學習成本。

下面我們就來看下LiveData怎么實現屬性監聽。

//監聽一個屬性
fun <T, A> LiveData<T>.observeState(
lifecycleOwner: LifecycleOwner,
prop1: KProperty1<T, A>,
action: (A) -> Unit
) {
this.map {
StateTuple1(prop1.get(it))
}.distinctUntilChanged().observe(lifecycleOwner) { (a) ->
action.invoke(a)
}
}
//監聽兩個屬性
fun <T, A, B> LiveData<T>.observeState(
lifecycleOwner: LifecycleOwner,
prop1: KProperty1<T, A>,
prop2: KProperty1<T, B>,
action: (A, B) -> Unit
) {
this.map {
StateTuple2(prop1.get(it), prop2.get(it))
}.distinctUntilChanged().observe(lifecycleOwner) { (a, b) ->
action.invoke(a, b)
}
}
internal data class StateTuple1<A>(val a: A)
internal data class StateTuple2<A, B>(val a: A, val b: B)
//更新State
fun <T> MutableLiveData<T>.setState(reducer: T.() -> T) {
this.value = this.value?.reducer()
}

  1. 如上所示,主要是添加一個擴展方法,也是通過distinctUntilChanged來實現防抖。
  2. 如果需要監聽多個屬性,例如兩個屬性有其中一個變化了就觸發刷新,也支持傳入兩個屬性。
  3. 需要注意的是LiveData默認是不防抖的,這樣改造后就是防抖的了,所以傳入相同的值是不會回調的。
  4. 同時需要注意下承載State的數據類需要防混淆。

簡單使用

上面介紹了LiveData如何實現屬性監聽,下面看下簡單的使用。

//頁面狀態,需要避免混淆
data class MainViewState(
val fetchStatus: FetchStatus = FetchStatus.NotFetched,
val newsList: List<NewsItem> = emptyList()
)
//ViewModel
class MainViewModel : ViewModel() {
private val _viewStates: MutableLiveData<MainViewState> = MutableLiveData(MainViewState())
//只需要暴露一個LiveData,包括頁面所有狀態
val viewStates = _viewStates.asLiveData()
private fun fetchNews() {
//更新頁面狀態
_viewStates.setState {
copy(fetchStatus = FetchStatus.Fetching)
}
viewModelScope.launch {
when (val result = repository.getMockApiResponse()) {
//...
is PageState.Success -> {
_viewStates.setState {
copy(fetchStatus = FetchStatus.Fetched, newsList = result.data)
}
}
}
}
}
}
//View層
class MainActivity : AppCompatActivity() {
private fun initViewModel() {
viewModel.viewStates.run {
//監聽newsList
observeState(this@MainActivity, MainViewState::newsList) {
newsRvAdapter.submitList(it)
}
//監聽網絡狀態
observeState(this@MainActivity, MainViewState::fetchStatus) {
//..
}
}
}
}

如上所示,其實使用起來也很簡單方便。

  1. ViewModel只需對外暴露一個ViewState,避免了定義多個可變不可變LiveData的問題。
  2. View層支持監聽LiveData的一個屬性或多個屬性,支持局部刷新。

總結

本文主要介紹了MVI架構下如何實現局部刷新,并重點介紹了Mavericks的基本使用與原理,并在其基礎上使用LiveData實現了屬性監聽與局部刷新。

通過以上方式,解決了MVI架構的性能問題,實現了MVI架構的更佳實踐。

如果你的ViewModel中定義了多個可變與不可變的LiveData,就算你不使用MVI架構,支持監聽LiveData屬性相信也可以幫助你精簡一定的代碼。

如果本文對你有所幫助,歡迎點贊關注Star~

責任編輯:龐桂玉 來源: 安卓開發精選
相關推薦

2018-11-06 12:32:02

多云云平臺云計算

2017-08-11 17:20:07

LinuxShell

2024-03-11 00:00:00

應用架構開發

2018-05-30 15:15:47

混合云公共云私有云

2022-03-02 15:31:32

架構網絡請求代碼

2017-07-18 16:40:31

AndroidLiveData

2018-05-24 09:00:45

2011-08-18 12:19:17

vSwitchVMNIC

2022-06-08 08:45:46

Redis緩存代碼

2013-09-23 11:35:46

戴爾

2017-05-29 08:18:11

Serverless架構軟件系統

2019-11-15 15:03:34

AI工業4.0制造業

2010-06-28 17:30:34

數據中心制冷風冷液冷

2011-12-13 14:26:25

IBM

2020-09-14 09:33:02

網絡

2023-11-14 20:51:08

2015-09-15 16:01:40

混合IT私有云IT架構

2020-03-09 11:04:49

華為5G運營商

2013-11-20 10:21:30

閃存

2022-04-18 09:41:14

Go架構設計
點贊
收藏

51CTO技術棧公眾號

日韩啪啪电影网| 国产主播自拍av| 日韩欧美国产片| 色哟哟中文字幕| 手机在线电影一区| 色综合中文综合网| 久久国产一区二区三区| 91国视频在线| 亚洲成人黄色片| 99久久99久久精品国产片果冰| 欧美性xxxxxxx| 国产伦精品一区二区三区免费视频| 色欲狠狠躁天天躁无码中文字幕 | 亚洲国产精品久久精品怡红院| 一区二区三区我不卡| 免费日韩一级片| 澳门成人av| 亚洲午夜一区二区三区| 96成人在线视频| 91嫩草|国产丨精品入口| 青青久久精品| 亚洲欧美偷拍另类a∨色屁股| 国产精品久久久久久久久借妻| 成人午夜剧场视频网站| а√在线中文网新版地址在线| 久久精品播放| 日韩av网站大全| 国内自拍在线观看| 一色桃子av在线| 国产成人精品免费在线| 欧美精品激情在线| a视频免费观看| 亚洲女同志freevdieo| 久久久噜噜噜久久人人看| 欧洲一区二区视频| 欧美波霸videosex极品| 日本久久久久| 色婷婷av一区二区三区软件| 偷拍视频一区二区| 最近中文字幕免费观看| 国产精品7m凸凹视频分类| 国产丝袜精品视频| 日本黄大片一区二区三区| 欧美xxxhd| 欧美国产精品专区| 亚洲free性xxxx护士白浆| 国产性70yerg老太| 伊人久久大香线蕉无限次| 欧美中文字幕一区| 蜜桃网站在线观看| 午夜视频1000| 免费高清成人在线| 久久99国产精品自在自在app| 国产麻豆剧传媒精品国产av| 成人av三级| 亚洲图片激情小说| 综合久久国产| 精品国产丝袜高跟鞋| 豆国产96在线|亚洲| αv一区二区三区| 国产无套丰满白嫩对白| 色天天久久综合婷婷女18| 在线成人激情黄色| 中文字幕99页| 日韩天堂在线| 亚洲精品va在线观看| 欧美福利一区二区三区| 国产又大又黄又爽| 激情成人综合| 爽爽爽爽爽爽爽成人免费观看| 日韩精品国产一区| 91精品店在线| 婷婷丁香久久五月婷婷| 一本一道久久久a久久久精品91| 成人乱码一区二区三区| 免费人成在线不卡| 国产色综合天天综合网| 女人十八岁毛片| 我不卡影院28| 欧美高清在线播放| 日韩av成人在线观看| 成人9ⅰ免费影视网站| 亚洲精品18p| 97se狠狠狠综合亚洲狠狠| 91精品久久久久久综合乱菊| 国产黄色片免费看| 久久久国产精品一区二区中文| 不卡av在线播放| 日本精品在线观看视频| 日韩精品欧美激情一区二区| 久久精品成人欧美大片| 国产精品久久久精品四季影院| 一区二区亚洲精品| 国产成人欧美在线观看| 日本中文字幕免费| 女人色偷偷aa久久天堂| 日韩中文字幕国产| 欧美老女人性生活视频| 综合久久十次| 久久国产精品99国产精| 青青操在线播放| 波多野结衣的一区二区三区| 亚洲黄在线观看| 18深夜在线观看免费视频| 中文字幕综合| 欧美二区在线观看| 国产美女18xxxx免费视频| 日韩经典一区| 精品视频免费在线| 性猛交ⅹ×××乱大交| jizz18欧美18| 日韩中文字幕在线| 中文字字幕在线中文| 国产在线精品一区二区| 91免费欧美精品| 国产又爽又黄又嫩又猛又粗| 99久久伊人精品| 久久国产精品亚洲va麻豆| 色婷婷av一区二区三区之e本道| 国产欧美视频一区二区三区| 日韩午夜视频在线观看| a√在线中文网新版址在线| 国产女主播视频一区二区| 久草视频国产在线| 性欧美又大又长又硬| 91精品在线观看入口| 深夜做爰性大片蜜桃| 涩爱av色老久久精品偷偷鲁| 欧美成人一区二区| 国产日韩欧美久久| 秋霞在线一区| 亚洲午夜av电影| 五月天色婷婷丁香| 欧美视频一区| 欧美做爰性生交视频| 不卡的日韩av| 久久亚洲精品国产精品紫薇| 欧美一区二区视频17c| av在线播放av| 日本电影亚洲天堂一区| 9.1成人看片| 亚洲经典在线| 国产精品高清网站| 欧美新色视频| 中文字幕制服丝袜成人av| 久久av高潮av| 一级毛片久久久| 亚洲精品720p| 免费日韩一级片| 97久久精品人人澡人人爽| 福利视频一二区| 国产精品国产| 在线观看视频亚洲| 精品人妻一区二区三区潮喷在线| 卡一卡二国产精品| 懂色一区二区三区av片| 日韩在线观看视频网站| 欧美经典一区二区三区| 国产三级日本三级在线播放| 成人久久精品| 亚洲欧美精品一区| 91日韩中文字幕| 国产剧情av麻豆香蕉精品| 另类欧美小说| 污视频网站在线免费| 在线精品视频小说1| 国产成人无码精品久久二区三| 一区二区三区国产精华| 亚洲综合av影视| 啦啦啦中文在线观看日本| 欧美丝袜自拍制服另类| 亚洲少妇18p| 免费看亚洲片| 国产精品一 二 三| 国产免费不卡| 综合欧美国产视频二区| 天堂网av手机版| 久久女同精品一区二区| 天天干天天综合| 91超碰国产精品| 国产精品第七十二页| 欧美69xxx| 欧美视频一区二区三区在线观看| 刘亦菲国产毛片bd| 噜噜爱69成人精品| 亚洲欧洲日夜超级视频| 国产精品专区免费| 啊v视频在线一区二区三区| 性生活三级视频| 色综合久久久久综合体| 亚洲xxxx3d动漫| 久久国产欧美日韩精品| 国产一区二区片| 激情综合婷婷| yellow中文字幕久久| 成人免费一级视频| 欧美在线free| 久久久综合久久久| 国产欧美一区在线| 91人人澡人人爽| 日本伊人色综合网| 午夜精品一区二区三区四区| 亚洲2区在线| 国产精品夜间视频香蕉| 在线a人片免费观看视频| 欧洲在线/亚洲| 久久综合综合久久| 中文幕一区二区三区久久蜜桃| 成人一区二区三区仙踪林| 蜜臀av性久久久久蜜臀aⅴ| 亚洲 自拍 另类小说综合图区| 日本久久一二三四| 韩国精品一区二区三区六区色诱| 6699嫩草久久久精品影院| 精品奇米国产一区二区三区| 中文字幕第99页| 国产精品传媒视频| 国产吞精囗交久久久| 亚洲大胆av| 在线视频不卡一区二区三区| 亚洲人成网77777色在线播放| 亚洲最大成人免费视频| 小明成人免费视频一区| 欧美亚洲视频一区二区| 久久久久久女乱国产| 欧洲精品一区二区| 国产精品黄色大片| 亚洲午夜免费电影| 欧美极品aaaaabbbbb| 成人黄色一级视频| 亚洲精品乱码久久久久久自慰| 国产麻豆精品久久| 成人免费看吃奶视频网站| 日本免费久久| 久久精品中文字幕| 91sp网站在线观看入口| 国产香蕉97碰碰久久人人| 视频在线不卡| 欧美欧美午夜aⅴ在线观看| 一区二区三区影视| 国产精品美女久久久久高潮| 久久婷婷中文字幕| 亚洲精品一级| 欧美国产日韩激情| 好吊一区二区三区| 日产精品一线二线三线芒果| 欧美一性一交| 久99久在线| 欧美网色网址| 久久艳妇乳肉豪妇荡乳av| 神马日本精品| 91视频国产一区| 亚洲国产一区二区久久| 国产欧美精品一区二区三区介绍| 麻豆久久久久| 午夜免费久久久久| 91最新在线| 色偷偷av一区二区三区乱| 婷婷五月在线视频| 日韩在线播放视频| www.在线视频| 国产性色av一区二区| 美州a亚洲一视本频v色道| 国产午夜精品免费一区二区三区| 精品美女视频在线观看免费软件| 91精品国产欧美一区二区成人| 日韩中文字幕在线观看视频| 色国产精品一区在线观看| 这里只有精品9| 午夜一区二区三区在线观看| 999精品视频在线观看播放| 亚洲视频1区2区| 国产亚洲精品久久777777| 婷婷中文字幕一区三区| 日韩欧美国产另类| 欧美日韩国产一区在线| 久久久精品一区二区涩爱| 亚洲成国产人片在线观看| 欧美做爰爽爽爽爽爽爽| 香蕉乱码成人久久天堂爱免费| 可以免费在线观看的av| 精品视频在线看| 蜜桃av噜噜一区二区三区麻豆| 日韩精品福利在线| 永久免费在线观看视频| 欧美国产乱视频| 欧美最新精品| 俄罗斯精品一区二区| 久久不见久久见中文字幕免费| 成人免费看片网站| 久久99高清| 日本福利视频网站| 日韩在线卡一卡二| aa视频在线播放| 男人的天堂亚洲一区| 99精品一区二区三区无码吞精| 国产精品一区二区在线观看不卡 | 在线看成人av| 在线观看日韩国产| 懂色av成人一区二区三区| 国产亚洲精品激情久久| 岛国毛片av在线| 精品视频9999| 欧美18av| 国产精品视频免费一区| 久久在线视频免费观看| 北条麻妃在线视频观看| 国产一区二区三区av电影| 国产熟妇搡bbbb搡bbbb| 一片黄亚洲嫩模| 精品无码黑人又粗又大又长| 欧美亚洲尤物久久| 天天干天天插天天操| 另类图片亚洲另类| 日韩欧美一区二区三区在线观看| 成人免费在线看片| 国产精品久久天天影视| 999在线免费视频| 久久久综合网站| 国产性xxxx高清| 亚洲精品一区二区三区精华液 | 一区高清视频| 视频一区二区欧美| 亚洲精品怡红院| 蜜桃精品视频在线观看| 亚洲做受高潮无遮挡| 偷拍一区二区三区四区| 人妻中文字幕一区| 欧美激情视频一区二区| www999久久| 自拍视频一区二区三区| 老司机免费视频一区二区| 波多野在线播放| 色综合久久99| 国产人成在线观看| 久久综合色88| 91成人福利社区| 亚洲精品无人区| 蜜桃av一区二区三区电影| 白白色免费视频| 欧洲在线/亚洲| freemovies性欧美| 欧美麻豆久久久久久中文| 欧美大片网站| 影音欧美亚洲| 国产一区二区三区日韩| 精品国产国产综合精品| 欧美理论片在线| 动漫一区在线| 99国产超薄肉色丝袜交足的后果| 欧美伊人久久| 国产免费a级片| 精品福利在线视频| 久久综合九色综合久| 国产精品九九久久久久久久| 欧美成人精品一区二区三区在线看| 一区二区三区入口| 成人av电影在线观看| 日本熟妇毛耸耸xxxxxx| 亚洲精品国产拍免费91在线| xxxxxx欧美| 亚洲人成影视在线观看| 狠狠色丁香婷婷综合久久片| 久久人妻少妇嫩草av无码专区| 亚洲成人一区二区在线观看| 天堂av电影在线观看| 国产成人a亚洲精品| 91综合网人人| 亚洲乱妇老熟女爽到高潮的片| 亚洲成人免费电影| 青青草娱乐在线| 91精品久久久久久久| 欧美激情日韩| 日韩中文字幕电影| 欧美久久高跟鞋激| av午夜在线观看| 日韩久久不卡| 国产毛片精品国产一区二区三区| 久久午夜无码鲁丝片午夜精品| 亚洲精品丝袜日韩| 欧美电影在线观看网站| 日本久久久网站| 国产欧美1区2区3区| www.99视频| 国产成人黄色av| 国产精品v欧美精品v日本精品动漫| 免费成人蒂法网站| 亚洲第一搞黄网站| av网页在线| 国产视频精品网| 亚洲第一区色| 精品无码人妻一区二区免费蜜桃| 91精品国产综合久久婷婷香蕉 | 狠狠爱在线视频一区| 在线观看av的网站| 国内精品久久国产| 国产一区二区三区四区五区入口| 黑人精品无码一区二区三区AV| 精品剧情v国产在线观看在线| 在线观看特色大片免费视频|