【问题标题】:Whats the difference between observing a variable and a function观察变量和函数有什么区别
【发布时间】:2020-07-22 20:36:09
【问题描述】:

当我从 Fragment A 观察我的视图模型中的一个变量时

val fetchTopicsList = liveData(Dispatchers.IO) {
        emit(Resource.Loading())
        try {
            emit(repo.getIdeas())
        }catch (e:Exception){
            emit(Resource.Failure(e))
        }
    }

然后我导航到 Fragment B 并返回 Fragment A,观察者将再次触发,但不会获取新数据。

现在,如果我将该声明更改为函数声明

fun fetchTopicsList() = liveData(Dispatchers.IO) {
        emit(Resource.Loading())
        try {
            emit(repo.getIdeas())
        }catch (e:Exception){
            emit(Resource.Failure(e))
        }
    }

当我做同样的事情时(从片段 A 到片段 B 并返回),观察者将再次触发并再次从服务器中提取数据。

为什么函数会再次触发而变量只保留第一个获取的数据?

【问题讨论】:

    标签: android kotlin mvvm viewmodel android-architecture-components


    【解决方案1】:

    您可能实际上想要一个 MutableLiveData 的单个实例,它会在某些交互时发出,但我想直接解决您的问题:

    使用该函数,每次调用都会为您提供LiveData 的新实例,而使用属性初始化程序将在实例化您的类时将其实例化+设置为LiveData 的单个实例。这意味着,如果您的属性位于 ViewModel 上,它将通过配置更改和暂停/恢复循环继续存在,直到它被销毁。

    如果您更喜欢属性语法,则可以通过覆盖 getter 使其每次重新调用函数时执行相同的操作,但老实说,这里的函数在语法上更准确。

    这是使用属性语法实现相同功能的方式:

    val fetchTopicsList: LiveData<..>
      get() = liveData(Dispatchers.IO) {
         emit(Resource.Loading())
         try {
           emit(repo.getIdeas())
         } catch (e:Exception){
           emit(Resource.Failure(e))
         }
      }
    

    同样,更好的方法可能是单个 MutableLiveData 并在 ViewModel 上公开一个函数以发出请求并为任何订阅者发布值。

    【讨论】:

    • 一般情况下,你要将LiveData缓存为一个字段,“refetch”应该由LiveData本身触发,使用emitSource监听。
    猜你喜欢
    • 2015-02-24
    • 1970-01-01
    • 1970-01-01
    • 2021-10-30
    • 2015-05-19
    • 2013-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多