[Day14] Android - Kotlin笔记:LiveData在fragment重建时会重新呼叫两次的解决方法

原因:

Activity中绑定一个ViewModel
Fragments间共用这个ViewModel
使用Naviagtion来切换Fragment间的页面时,
每次切换都会重走一次Fragment的生命周期,
也就是处於“STARTED 或 RESUMED 状态”,
导致从其他页面切换回来之後,
会触发LiveData的数据回调(observer被触发)。


举例:

Activity中保存一个ViewModel
使用NavigationFragment实现页面的切换,
AFragment获取ActivityViewModel并注册LiveDataobserver
此时使用setValueAFragment收到一次LiveData数据,
然後切换到BFragmentAFragment被销毁),
之後切回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间切换影响而重复调用。


参考:


<<:  # Day 8 Why the “volatile” type class should not be used

>>:  [Day2] 自我必备觉醒力:自觉的力量

Day_01: 让 Vite 来开启你的Vue 前言

Hi Da Gei Ho~ 初次见面,我是Winnie~ 我是一位刚转职六个月的菜鸟前端(前身是网页...

[DAY 27] 章节3-7: 对立的鸡群们- k-means(k平均分类演算法) (1/2)

3-7 对立的鸡群们 在飞哥的工作室也待好一阵子的小博,这天在网路上收集资料,以便帮飞哥在报告上有更...

[从0到1] C#小乳牛 练成基础程序逻辑 Day 5 - 资料类型 $字串插补

你喜欢什麽类型? | 实质的那一种 | $$$$$$爱了 🐄点此填写今日份随堂测验 ...

Day 12: 验收测试、测试策略 (待改进中... )

「验收测试的目的是沟通、澄清及精确化。从专业开发人员的眼光来看,与业务方、测试方协同工作,确保大家...

Day 30:「很刺眼,这样太亮了啦!」- 深色模式切换开关

「最近眼睛都一直盯着电脑,超酸的」 「而且这台萤幕还坏掉,不能调整亮度」 这样啊 ... 辛苦了,...