前言
在前幾年興起了MVVM架構設計模式,最具有代表的框架就是DataBinding,雖然這種設計架構非常新穎,但是在使用中仍然還有很多痛點,所以我當時覺得短時間這個設計架構可能不會太流行。
最近接手了新項目,使用的就是MVVM,才發現只一兩年的功夫MVVM的發展竟然這麼快,已經是Android開發者必備的技能之一了。
正文
DataBinding在剛開始階段,最令我頭疼的就是數據處理的問題,往往為了顯示數據,我要在XML中綁定N多個字段,如果是一箇中等以上的工程,還有更蛋疼的問題,例如:
- 你的XML可能迫切的需要if或者switch這樣的判斷;
- 意想不到的空指針
在2018年,Google推出JetPack庫,其中的ViewModel+LIveData終於把MVVM推上了新的高度。
ViewModel
使用ViewModel需要依賴lifecycle庫:
<code> implementation "android.arch.lifecycle:viewmodel:x.x.x"
implementation "android.arch.lifecycle:extensions:x.x.x"
/<code>
ViewModel的創建方法主要有兩種:
<code> // 獲取FragmentActivity共享的ViewModel
ViewModelProviders.of(FragmentActivity).get(ViewModel::class.java)
// 獲取FragmentActivity共享的ViewModel
ViewModelProviders.of(Fragment).get(ViewModel::class.java)
/<code>
ViewModel的共享範圍主要有兩種:一種是FragmentActivity,一種是Fragment,可以根據自己的需要選擇共享的範圍。如果你想要一個Application級別的ViewModel,目前是不支持的,你可以自定義Application持有一個ViewModel,或者使用單例模式。
ViewModel解決的問題
1、擴大數據共享的應用場景。
一般的數據共享是Activity與Fragment的數據傳遞,傳統做法是使用setArguments(Bundle),這種方法有以下弊端:
- 可能無法預測setArguments會在Fragment的哪個週期完成,要進行異常判斷;
- setArguments中的數據可能會發現改變,如果是Activity直接設置Fragment的數據,耦合性很高;
- 數據較多時,Fragment會有很多的變量,影響可讀性和維護性。
使用ViewModel,可以避免以上的尷尬情況,需要什麼數據就從ViewModel中取:
- 新加數據傳遞,不用修改Activity的setArguments代碼,Fragment也不用編寫數據接收的方法;
- 減少數據傳遞,不必考慮是否要刪除暫時無用的代碼;
- 取數據時,請注意數據的有效性,做好判斷即可;
除此之外,自定義View也可以得到ViewModel,這樣某些功能耦合性非常強的自定義View開發更加便捷。不過需要注意的是View的context的上下文是Activity類型(不會是Fragment)的,所以只能使用Activity級別的數據共享。
2、解決DataBinding的視圖顯示問題。
如果視圖的顯示需要很多的數據,那麼XML就會變得越來越臃腫,並且迫切需要添加一些簡單的判斷,例如:
如果A為空就顯示B,如果B為空就先是C,如果是C為空...
雖然DataBinding支持三元運算符,能夠滿足if判斷的需要,但是很顯然在XML維護邏輯要比Java或者Kotlin要困難的多(無拼寫錯誤提示等)。所以我們非常需要把部分代碼從XML分離出來,ViewModel就非常適合擔任這個角色。
修改前:
<code>
<layout>
<data>
<variable> name="A"
type="String" />
<variable> name="B"
type="String" />
<variable> name="C"
type="String" />
/<variable>/<variable>/<variable>/<data>
<textview> android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="4"
android:ellipsize="middle"
android:text="A != null ? A : B != null ? B : C" />
...
/<textview>/<layout>
/<code>
修改後:
<code>
<layout>
<data>
<variable> name="viewModel"
type="ViewModel" />
/<variable>/<data>
<textview> android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="4"
android:ellipsize="middle"
android:text="@{viewModel.getShowContent()}" />
...
/<textview>/<layout>
/<code>
LiveData
剛才我們已經討論了ViewModel的用法,但是還有一個問題沒有解決,那就是數據更新的問題,解決這個問題的最佳方式就是觀察者模式,但是如果沒有處理好觀察者的註冊和解綁很容易出現內存溢出。LiveData就可以完美的解決這個問題。
我們需要添加LiveData的依賴:
<code> implementation "androidx.lifecycle:lifecycle-livedata:2.1.0"
/<code>
下面是一個簡單的示例:
<code> // 名為openDrawer的Boolean類型的LiveData
public final MutableLiveData<boolean> openDrawer = new MutableLiveData<>();
// 更新openDrawer
openDrawer.setValue(true)
// 觀察openDrawer 的值的變化
openDrawer.observe(this, aBoolean -> {
Toast.makeText(this, "${aBoolean}", Toast.LENGTH_SHORT).show();
});
/<boolean>/<code>
LiveData的子類是MutableLiveData,內部有value屬性保存最新的值,訂閱LiveData的變化,直接調用LiveData.observe():
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer super T> observer)owner:註冊的週期,會在owner銷燬的時候,解綁觀察者。observer:觀察的值發生變化的回調函數
owner直接使用Activity或者Fragment即可。如果你還不瞭解Lifecycle的使用,可以查看一下相關的資料。
總結
最後我畫了一張架構圖,總結了一下最新的MVVM的使用架構:
Activity:處理UI問題,但是應當儘量避免這樣做,儘量統一使用DataBinding。ViewModel:保存頁面需要的數據,功能複雜的話可以拆分成多個。DataBinding:處理UI視圖,持有ViewModel做數據展示。如果頁面功能比較複雜,可以對ViewModel和DataBinding再次細分。
最後有話說
對於進階這條路而言,學習是會有回報的!
你把你的時間投資在學習上,就意味著你可以收穫技能,更有機會增加收入。
在這裡分享我的Android學習PDF大全來學習,這份Android學習PDF大全真的包含了方方面面了,內含Java基礎知識點、Android基礎、Android進階延伸、算法合集等等
我的這份學習合集,可以有效的幫助大家掌握知識點。
總之也是在這裡幫助大家學習提升進階,也節省大家在網上搜索資料的時間來學習,也可以分享給身邊好友一起學習
獲取方式:關注+轉發,私信我【核心】即可
閱讀更多 Android01 的文章