mb612e277c48155 2021-09-18 03:34:43 阅读数:978
讓這些流持續活躍可能會引起不必要的資源浪費,例如一直通過從數據庫連接、硬件傳感器中讀取數據等等。當您的應用轉而在後臺運行時,您應當保持克制並中止這些協程。
如上所示,它支持兩個參數:
1.stopTimeoutMillis
控制一個以毫秒為單比特的延遲值,指的是最後一個訂閱者結束訂閱與停止上遊流的時間差。默認值是 0 (立即停止).這個值非常有用,因為您可能並不想因為視圖有幾秒鐘不再監聽就結束上遊流。這種情况非常常見——比如當用戶旋轉設備時,原來的視圖會先被銷毀,然後數秒鐘內重建。
2.replayExpirationMillis
錶示數據重播的過時時間,如果用戶離開應用太久,此時您不想讓用戶看到陳舊的數據,你可以用到這個參數
4. StateFlow
介紹
StateFlow
我們前面剛剛看了SharedFlow
,為什麼又冒出個StateFlow
?
StateFlow
是 SharedFlow
的一個比較特殊的變種,StateFlow
與 LiveData
是最接近的,因為:
1.它始終是有值的。
2.它的值是唯一的。
3.它允許被多個觀察者共用 (因此是共享的數據流)。
4.它永遠只會把最新的值重現給訂閱者,這與活躍觀察者的數量是無關的。
可以看出,StateFlow
與LiveData
是比較接近的,可以獲取當前的值,可以想像之所以引入StateFlow
就是為了替換LiveData
總結如下:
1.StateFlow
繼承於SharedFlow
,是SharedFlow
的一個特殊變種
2.StateFlow
與LiveData
比較相近,相信之所以推出就是為了替換LiveData
StateFlow
的簡單使用我們先來看看構造函數:
1.StateFlow
構造函數較為簡單,只需要傳入一個默認值
2.StateFlow
本質上是一個replay
為1,並且沒有緩沖區的SharedFlow
,因此第一次訂閱時會先獲得默認值
3.StateFlow
僅在值已更新,並且值發生了變化時才會返回,即如果更新後的值沒有變化,也沒會回調Collect
方法,這點與LiveData
不同
與StateFlow
類似,我們也可以用stateIn
將普通流轉化成SharedFlow
與shareIn
類似,唯一不同的時需要傳入一個默認值
同時之所以WhileSubscribed
中傳入了5000
,是為了實現等待5
秒後仍然沒有訂閱者存在就終止協程的功能,這個方法有以下功能
用戶將您的應用轉至後臺運行,5 秒鐘後所有來自其他層的數據更新會停止,這樣可以節省電量。
最新的數據仍然會被緩存,所以當用戶切換回應用時,視圖立即就可以得到數據進行渲染。
訂閱將被重啟,新數據會填充進來,當數據可用時更新視圖。
在屏幕旋轉時,因為重新訂閱的時間在5s內,因此上遊流不會中止
StateFlow
與LiveData
類似,我們也需要經常在頁面中觀察StateFlow
觀察StateFlow
需要在協程中,因此我們需要協程構建器,一般我們會使用下面幾種
lifecycleScope.launch
: 立即啟動協程,並且在本 Activity
或Fragment
銷毀時結束協程。
LaunchWhenStarted
和 LaunchWhenResumed
,它會在lifecycleOwner
進入X
狀態之前一直等待,又在離開X
狀態時掛起協程
如上圖所示:
1.使用launch
是不安全的,在應用在後臺時也會接收數據更新,可能會導致應用崩潰
2.使用launchWhenStarted
或launchWhenResumed
會好一些,在後臺時不會接收數據更新,但是,上遊數據流會在應用後臺運行期間保持活躍,因此可能浪費一定的資源
這麼說來,我們使用WhileSubscribed
進行的配置豈不是無效了嗎?訂閱者一直存在,只有頁面關閉時才會取消訂閱
官方推薦repeatOnLifecycle
來構建協程
在某個特定的狀態滿足時啟動協程,並且在生命周期所有者退出該狀態時停止協程,如下圖所示。
比如在某個Fragment
的代碼中:
當這個Fragment
處於STARTED
狀態時會開始收集流,並且在RESUMED
狀態時保持收集,最終在Fragment
進入STOPPED
狀態時結束收集過程。
結合使用repeatOnLifecycle API
和WhileSubscribed
,可以幫助您的應用妥善利用設備資源的同時,發揮最佳性能
Flow
的最佳方式通過ViewModel
暴露數據,並在頁面中獲取的最佳方式是:
WhileSubscribed
策略暴露 Flow
。[示例 1]()
repeatOnLifecycle
來收集數據更新。[示例 2]()
最佳實踐如上圖所示,如果采用其他方式,上遊數據流會被一直保持活躍,導致資源浪費
當然,如果您並不需要使用到Kotlin Flow
的强大功能,就用LiveData
好了
5 StateFlow
與SharedFlow
有什麼區別?
從上文其實可以看出,StateFlow
與SharedFlow
其實是挺像的,讓人有些傻傻分不清,有時候也挺難選擇該用哪個的
我們總結一下,它們的區別如下:
SharedFlow
配置更為靈活,支持配置replay
,緩沖區大小等,StateFlow
是SharedFlow
的特化版本,replay
固定為1,緩沖區大小默認為0
StateFlow
與LiveData
類似,支持通過myFlow.value
獲取當前狀態,如果有這個需求,必須使用StateFlow
SharedFlow
支持發出和收集重複值,而StateFlow
當value
重複時,不會回調collect
對於新的訂閱者,StateFlow
只會重播當前最新值,SharedFlow
可配置重播元素個數(默認為0,即不重播)
可以看出,StateFlow
為我們做了一些默認的配置,在SharedFlow
上添加了一些默認約束,這些配置可能並不符合我們的要求
它忽略重複的值,並且是不可配置的。這會帶來一些問題,比如當往List
中添加元素並更新時,StateFlow
會認為是重複的值並忽略
它需要一個初始值,並且在開始訂閱時會回調初始值,這有可能不是我們想要的
它默認是粘性的,新用戶訂閱會獲得當前的最新值,而且是不可配置的,而SharedFlow
可以修改replay
StateFlow
施加在SharedFlow
上的約束可能不是最適合您,如果不需要訪問myFlow.value
,並且享受SharedFlow
的靈活性,可以選擇考慮使用SharedFlow
總結
–
簡單往往意味著不够强大,而强大又常常意味著複雜,兩者往往不能兼得,軟件開發過程中常常面臨這種取舍。
LiveData
的簡單並不是它的缺點,而是它的特點。StateFlow
與SharedFlow
更加强大,但是學習成本也顯著的更高.
我們應該根據自己的需求合理選擇組件的使用
如果你的數據流比較簡單,不需要進行線程切換與複雜的數據變換,LiveData
對你來說相信已經足够了
如果你的數據流比較複雜,需要切換線程等操作,不需要發送重複值,需要獲取myFlow.value
,StateFlow
對你來說是個好的選擇
如果你的數據流比較複雜,同時不需要獲取myFlow.value
,需要配置新用戶訂閱重播無素的個數,或者需要發送重複的值,可以考慮使用SharedFlow
[Google 推薦在 MVVM 架構中使用 Kotlin Flow](
)
[Migrate from LiveData to StateFlow and SharedFlow](
)
[從 LiveData 遷移到 Kotlin 數據流](
)
[關於kotlin中的Collections、Sequence、Channel和Flow (二)](
)
其他資料
在這裏我和身邊一些朋友特意整理了一份快速進階為Android高級工程師的系統且全面的學習資料。涵蓋了Android初級——Android高級架構師進階必備的一些學習技能。
附上:我們之前因為秋招收集的二十套一二線互聯網公司Android面試真題(含BAT、小米、華為、美團、滴滴)和我自己整理Android複習筆記(包含Android基礎知識點、Android擴展知識點、Android源碼解析、設計模式匯總、Gradle知識點、常見算法題匯總。)
本文在 CodeChina開源項目:《Android學習筆記總結+移動架構視頻+大廠面試真題+項目實戰源碼》中已收錄,裏面包含不同方向的自學編程路線、面試題集合/面經、及系列技術文章等
版权声明:本文为[mb612e277c48155]所创,转载请带上原文链接,感谢。 https://gsmany.com/2021/09/20210918033443040l.html