在Activity
中綁定一個ViewModel
,
Fragments
間共用這個ViewModel
,
使用Naviagtion
來切換Fragment
間的頁面時,
每次切換都會重走一次Fragment
的生命週期,
也就是處於“STARTED 或 RESUMED 狀態”,
導致從其他頁面切換回來之後,
會觸發LiveData
的數據回調(observer被觸發)。
在Activity
中保存一個ViewModel
,
使用Navigation
和Fragment
實現頁面的切換,
AFragment
獲取Activity
的ViewModel
並註冊LiveData
為observer
,
此時使用setValue
讓AFragment
收到一次LiveData
數據,
然後切換到BFragment
(AFragment
被銷毀),
之後切回AFragment
,會發現重新註冊LiveData
數據,
AFragment
再次收到LiveData
數據。
圖源:https://bbs.huaweicloud.com/blogs/detail/256402
新增一個Event
class
open class Event<out T>(private val content: T) {
var hasBeenHandled = false
private set // Allow external read but not write
/**
* Returns the content and prevents its use again.
*/
fun getContentIfNotHandled(): T? {
return if (hasBeenHandled) {
null
} else {
hasBeenHandled = true
content
}
}
/**
* Returns the content, even if it's already been handled.
*/
fun peekContent(): T = content
}
用Event
包裝你原本的data。
ViewModel
層 val selectedDate: LiveData<Event<String?>>
get() = _selectedDate
private val _selectedDate = MutableLiveData<Event<String?>>()
fun setSelectedDate(date: String?) {
_selectedDate.value = Event(date)
}
Fragment
層 viewModel.selectedDate.observe(viewLifecycleOwner, {
it.getContentIfNotHandled()?.apply { result ->
tv_selectedDate.text = result
}
})
透過getContentIfNotHandled
取得Event
中原本的LiveData
,
能夠抓取正確值,
而不會一直被Fragment
間切換影響而重複調用。
參考: