在前幾年興起了
MVVM
架構(gòu)設(shè)計模式,最具有代表的框架就是
DataBinding
,雖然這種設(shè)計架構(gòu)非常新穎,但是在使用中仍然還有很多痛點,所以我當(dāng)時覺得短時間這個設(shè)計架構(gòu)可能不會太流行。
最近接手了新項目,使用的就是
MVVM
,才發(fā)現(xiàn)只一兩年的功夫
MVVM
的發(fā)展竟然這么快,已經(jīng)是Android開發(fā)者必備的技能之一了。
DataBinding
在剛開始階段,最令我頭疼的就是數(shù)據(jù)處理的問題,往往為了顯示數(shù)據(jù),我要在
XML
中綁定
N
多個字段,如果是一個中等以上的工程,還有更蛋疼的問題,例如:
XML
可能迫切的需要
if
或者
switch
這樣的判斷;在2018年,
Google
推出
JetPack
庫,其中的
ViewModel+LIveData
終于把
MVVM
推上了新的高度。
使用
ViewMode
l需要依賴
lifecycle
庫:
implementation "android.arch.lifecycle:viewmodel:x.x.x" implementation "android.arch.lifecycle:extensions:x.x.x"
ViewModel
的創(chuàng)建方法主要有兩種:
// 獲取FragmentActivity共享的ViewModel ViewModelProviders.of(FragmentActivity).get(ViewModel::class.java) // 獲取FragmentActivity共享的ViewModel ViewModelProviders.of(Fragment).get(ViewModel::class.java)
ViewModel
的共享范圍主要有兩種:一種是
FragmentActivity
,一種是
Fragment
,可以根據(jù)自己的需要選擇共享的范圍。如果你想要一個
Application
級別的
ViewModel
,目前是不支持的,你可以自定義
Application
持有一個
ViewModel
,或者使用單例模式。
1、擴(kuò)大數(shù)據(jù)共享的應(yīng)用場景。
一般的數(shù)據(jù)共享是
Activity
與
Fragment
的數(shù)據(jù)傳遞,傳統(tǒng)做法是使用
setArguments(Bundle)
,這種方法有以下弊端:
setArguments
會在
Fragment
的哪個周期完成,要進(jìn)行異常判斷;setArguments
中的數(shù)據(jù)可能會發(fā)現(xiàn)改變,如果是
Activity
直接設(shè)置
Fragment
的數(shù)據(jù),耦合性很高;Fragment
會有很多的變量,影響可讀性和維護(hù)性。使用
ViewModel
,可以避免以上的尷尬情況,需要什么數(shù)據(jù)就從
ViewModel
中?。?/p>
Activity
的
setArguments
代碼,
Fragment
也不用編寫數(shù)據(jù)接收的方法;除此之外,自定義
View
也可以得到
ViewModel
,這樣某些功能耦合性非常強的自定義
View
開發(fā)更加便捷。不過需要注意的是
View
的
context
的上下文是
Activity
類型(不會是
Fragment
)的,所以只能使用
Activity
級別的數(shù)據(jù)共享。
2、解決DataBinding的視圖顯示問題。
如果視圖的顯示需要很多的數(shù)據(jù),那么
XML
就會變得越來越臃腫,并且迫切需要添加一些簡單的判斷,例如:
如果A為空就顯示B,如果B為空就先是C,如果是C為空...
雖然
DataBinding
支持三元運算符,能夠滿足if判斷的需要,但是很顯然在
XML
維護(hù)邏輯要比
Java
或者
Kotlin
要困難的多(無拼寫錯誤提示等)。所以我們非常需要把部分代碼從
XML
分離出來,
ViewModel
就非常適合擔(dān)任這個角色。
修改前:
...
修改后:
...
剛才我們已經(jīng)討論了
ViewModel
的用法,但是還有一個問題沒有解決,那就是數(shù)據(jù)更新的問題,解決這個問題的最佳方式就是觀察者模式,但是如果沒有處理好觀察者的注冊和解綁很容易出現(xiàn)內(nèi)存溢出。
LiveData
就可以完美的解決這個問題。
我們需要添加
LiveData
的依賴:
implementation "androidx.lifecycle:lifecycle-livedata:2.1.0"
下面是一個簡單的示例:
// 名為openDrawer的Boolean類型的LiveData public final MutableLiveDataopenDrawer = new MutableLiveData<>(); // 更新openDrawer openDrawer.setValue(true) // 觀察openDrawer 的值的變化 openDrawer.observe(this, aBoolean -> { Toast.makeText(this, "${aBoolean}", Toast.LENGTH_SHORT).show(); });
LiveData
的子類是
MutableLiveData
,內(nèi)部有
value
屬性保存最新的值,訂閱
LiveData
的變化,直接調(diào)用
LiveData.observe()
:
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer super T> observer)
owner:注冊的周期,會在owner銷毀的時候,解綁觀察者。
observer:觀察的值發(fā)生變化的回調(diào)函數(shù)
owner
直接使用
Activity
或者
Fragment
即可。如果你還不了解
Lifecycle
的使用,可以查看一下相關(guān)的資料。
最后我畫了一張架構(gòu)圖,總結(jié)了一下最新的
MVVM
的使用架構(gòu):