当前位置: 首页 > 知识库问答 >
问题:

观察ViewModel中的LiveData最佳实践

宰父疏珂
2023-03-14

我正在寻找在ViewModel中观察数据的最佳方法。

我正在使用MVVM数据绑定。

存储库:

private val data = MutableLiveData<String>()

suspend fun getData(): LiveData<String> {
        return withContext(IO) {
            val response = apiRequest { api.getData() }
            data.postValue(response)
            data
        }
    }

它从服务器请求数据并返回实时数据。ViewModel必须观察数据更改。

视图模型:

    suspend fun getData() {
        val data = repository.getData()
        MediatorLiveData<String>().apply {
            addSource(data) {
                gotData(it)
                removeSource(data)
            }
            observeForever { }
        }
    }

    private fun gotData(data: String) {
        //use data
    }

ViewModel使用一个MediatorLiveData来观察来自存储库的LiveData的变化。我添加了数据作为源来观察变化,并在它触发后将其删除,以防止在我多次获取数据时多次触发事件。并且必须有一个虚假的观察者来观察MediatorLiveData,因此MediatorLiveData触发器的onChange方法。

比方说,我只需要数据来隐藏/显示视图(甚至将数据填充到我的recyclerview的adaper)。然后我调用下面的代码并使用如下可观察和数据绑定:

val adapter: ObservableField<DataAdapter> = ObservableField()
val recyclerviewVisibility: ObservableField<Int> = ObservableField(View.GONE)
...
...
recyclerviewVisibility.set(View.VISIBLE)
adapter.set(DataAdapter(dataList))

因此,我不需要将数据传递到FragmentActivity来使用viewLifecycleOwner。我也不能在ViewModel中使用observeforver,因为在某些情况下,它可能会多次触发onChange方法。

有没有更好的方法来获取和观察ViewModel中的数据?

解决方案:

我发现,达到我的目标的最好方法是从存储库中获取数据,而不使用LiveData

存储库

suspend fun getData() : String{
    return  apiRequest { api.getData() }
}

视图模型

suspend fun getData(){
   val data = repository.getData()
    gotData(data)
}

fun gotData(data: String) {
    //use data
}

现在简单多了。

奖金:

分机:

fun <T : Any> ViewModel.request(request: suspend () -> (T), result: (T) -> (Unit) = {}) {
    viewModelScope.launch {
        result(request())
    }
}

用法:

request({request.getData()}) {
    //use data
}

共有1个答案

端木承业
2023-03-14

如果我解决了这个问题,我想你可以在LiveData上使用map转换。

也许最好更改存储库代码,如下所示:

private val reload = MutableLiveData<Unit>()

val data: LiveData<String> =
    reload.switchMap {
        liveData(IO) {
            emit(apiRequest { api.getData() })
        }
    }

fun reload() {
    reload.postValue(Unit) 
}

然后,在您的ViewModel中,使用map Transtram,您可以截取发出的值:

val data: LiveData<String> = 
    repository.data.map {
        gotData(it)
        it
    }

fun reload() {
    repository.reload() 
}

使用此结构,您将能够在需要的任何时候调用ViewModel的reload(),从而从api获取新数据,并将其发送到ViewModel的数据上。

 类似资料:
  • 我有一个单独的类来处理数据提取(特别是Firebase),我通常从它返回LiveData对象并异步更新它们。现在我希望将返回的数据存储在ViewModel中,但问题是为了获得所述值,我需要观察从数据提取类返回的LiveData对象。observe方法需要一个LifecycleOwner对象作为第一个参数,但我的ViewModel中显然没有这个对象,而且我知道我不应该在ViewModel中保留对ac

  • 此外,为什么Viewmodel不能观察到它自己的LiveData的变化?

  • 我是一个新的Android开发人员,我正试图观察ViewModel中的布尔集。当应用程序启动时,我可以观察到它的初始状态,但以后应用的任何更改似乎都不会触发观察者(即当我切换片段时)。 下面是我的ViewModel的代码: 万事如意, 晶圆厂。

  • 对于LiveData和MVVM架构,我完全是个新手。我想知道如何观察一个实时数据 我通过以下方式从我的房间数据库中获取实时数据: 我希望ViewModel中的另一个变量,,在列表返回空(null)时进行更新。这将用于从Visible更新片段中的ImageView。去看电视了。看得见的 我如何检查如果是空的同步? 我四处阅读,看到一些人说使用,但是架构指南明确建议不要使用ViewModel中的任何观

  • 我一直在苦苦思考,在新的Android推荐架构中,Android服务应该放在哪里。我想出了许多可能的解决方案,但我无法决定哪一个是最好的方法。 我做了很多研究,但我找不到任何有用的指南或教程。关于在我的应用架构中放置服务的唯一提示是这个,来自@JoseAlcerreca Media的帖子 理想情况下,ViewModels不应该了解Android。这提高了可测试性、泄漏安全性和模块化。一般的经验法则

  • 我在我的Android应用程序中遵循MVVM架构。(https://developer.android.com/jetpack/guide)。我所有的存储库函数都返回一个网络边界资源对象。你可以从jetpack指南链接中阅读更多关于这个设计实现的信息,或者从谷歌这里查看示例项目 在这个特殊的问题中,当我在屏幕上下拉时,我试图通过网络重新获取信息。 目前的工作执行情况 片段侦听器(当屏幕下拉时触发)