這幾天突擊學了一下arc, 自然navigation, MVVM, lifecycle, DataBinding, LiveData, ViewModel這些概念也都得看.
幾種開發模式的對比
如何構建Android MVVM 應用框架
這篇算是我覺得寫的很清晰的了, 廢話少. 但是我對下面這句保留意見
"每個ViewModel都最好需要持了一個Context的引用" --- 其實谷歌官方還是不建議ViewModel持有context的, 如果有什么工具方法必須用到context, 在方法里面自己去找application的context就好了, 現在有了kotlin, 很多之前覺得不好看的代碼, 都可以一筆帶過.
google官方示例
google官方示例
官方的實例, 查看它的todo-mvvm-databing分支, 在README中有如下的描述:
The ViewModel in the MVVM architecture plays a similar role to the Presenter in the MVP architecture. The two architectures differ in the way that the View communicates with the ViewModel or Presenter respectively:
--ViewModel 在MVVM 中的作用與Presenter 在mvp中的作用類似, 這兩種架構的不同之處在于view組件與ViewModel 和Presenter 的通訊方式.
When the app modifies the ViewModel in the MVVM architecture, the View is automatically updated by a library or framework. You can’t update the View directly from the ViewModel, as the ViewModel doesn't have access to the necessary reference.
--- 當MVVM 中的ViewModel 變化時, View會自動被系統更新, 你不能在ViewModel中手工更新View, 客觀上這是做不到的.You can however update the View from the Presenter in an MVP architecture as it has the necessary reference to the View. When a change is necessary, you can explicitly call the View from the Presenter to update it.
In this project, you use layout files to bind observable fields in the ViewModel to specific UI elements such as a TextView, or ImageView. The Data Binding Library ensures that the View and ViewModel remain in sync bi-directionally as illustrated by the following diagram.
---- 但是在MVP中, 你必須通過Presenter 對View層進行修改. 通過句柄或者回調. 在這個項目中, 你使用布局文件來綁定fields 到UI控件. 比如TextView, ImageView. Data Binding Library會保證view與ViewModel的同步.
不管是mvp還是mvvm , 谷歌都把m實現成repository, 完全不以m開頭.
LifeCycle
關于lifecycle, 學習這幾篇
https://developer.android.google.cn/topic/libraries/architecture/lifecycle
http://www.lxweimin.com/p/9b3da5fe0ff6
http://www.lxweimin.com/p/ee6b81b9777a
基本上也就看懂了, 內容不算多, 就是通過類庫提供了一種機制, 可以知道activity
或者fragment的生命周期, 注意, 是在這兩個上下文之外可以知道這兩者的生命周期.
這帶來兩個好處:
1. 對于代碼來說, 更簡潔, 與activity, fragment的耦合少了.
2. 為一些需要在后臺處理的操作提供了方便的接口可以得知當前的生命周期變化.
認真記住官方文檔中的最佳實踐 best practise
LifeCycle best practise
1. 保持 UI controllers (activities and fragments)越簡潔越好,不要臃腫 。UI controllers不要去獲取數據,而是用ViewModel來執行,并監聽lifeData來更新視圖。
2. 嘗試編寫用數據驅動的UI,UI controllers的職責就是數據改變是更新視圖,并且把用戶的操作通知給ViewModel。
3. 將業務邏輯放入在VIewModel中,VIewModel應該用作UI控制器和其他應用程序之間的連接器。請注意,ViewModel的責任不是獲取數據(例如從網絡獲取數據),ViewModel應該調用相應的組件來獲取數據,然后把結果提供給UI controller。
4. 使用數據綁定來維護視圖view和UI控制器接口的清潔。使view視圖更具有生命性,減少在fragment或者activity編寫更新數據的代碼。如果使用Java語言來開發,請使用像Butter Knife這樣的庫來避免使用樣板代
5. 如果UI非常復雜,可以考慮創建一個Persenter類來處理UI的修改。也許使用Persenter有點大材小用,但是可以使ui變得更容易測試
6. 不要在ViewModel中引用View或者Activity中的context,如果ViewModel活的比Activity更長,activity可能會引發內存泄露,而不是正常的垃圾回收。
LifeCycle Event 和 State
Lifecycle類中兩個主要的枚舉: Event 和 State
LifecycleObserver類是一個接口, 而且是一個空接口:
public interface LifecycleObserver {
}
在實現這個接口的自定義observer類中, 需要通過注解的方式, 來對應具體的事件
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME) public void onMyResume() { } @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) public void onMyPause() { }
對于方法名, onMyResume, onMyPause就不重要了, 隨意取.
個方法可以觀察多個事件,多個方法也可以觀察相同事件
如果想深究一下原理, 看看這篇里面的簡單說明:http://www.lxweimin.com/p/ee6b81b9777a
補充一點, 如果是在普通Activity類中, 如果要實現LifecycleOwner 接口, 那么在提供LifecycleRegistry 對象之外, 還需要手工的在onCreate, onresume, onStart.....各個生命周期方法中去觸發事件. 很麻煩, 所以還是盡量使用support包中的SupportActivity子類吧.
LiveData
那么LiveData又是什么呢?
LiveData是一個機制, 一個接口(實際是幾個類), 一種方式,
可能還是得附屬到ViewModel 上, 來存儲數據,
這篇文章:http://www.lxweimin.com/p/14af4b8c29e3 中認為LiveData是用來監聽數據變化的. 框架提供了一種監聽者的模式, 來保證在LiveData數據變化時通知監聽者Observer,
先繼續說LiveData, 這個監聽跟之前的各種監聽器, 或者自己實現一個監聽器, 有什么區別呢? 最大的區別就是這里的監聽考慮了監聽者的生命周期變化, 如果一個Activity已經pause或者destory了, 那么就不會收到這個狀態變化的回調, 怎么做到的? 當然前面提到的LifeCycle框架.
關于LiveData, 最好的還是官方的這個指導
https://developer.android.google.cn/topic/libraries/architecture/livedata
其中最后提到了transformations, Transformations.switchMap
遇到的問題
使用mvvm 或者說使用DataBingding時, 經常遇到as誤報的編譯錯誤, clean一遍, 然后再編譯就成功了.
另外大部分的xml語法錯誤, 都無法在編譯失敗的信息里明確提示出來, 這是使用DataBinding的一個比較不好的地方.
---- 升級為最新的版本, 3.3canary6版本, 好一些了.
如果要在fragment中使用空間名稱來引用控件, 必須在onViewCreated()方法中, 如果是在onCreateView() 可能會報空指針.
如何向MutableLiveData<MutableList<String>>()中添加數據?
adapter.submitList()之后, 數據沒有刷新, 為什么? 做錯了什么?
----http://www.lxweimin.com/p/91b7c3bcb29f
代碼
https://github.com/shaopx/LiteDig -- 首頁-> "關注" 這個列表是使用的mvvm方式開發的