android - 观察 Android LiveData从 ViewModel 返回 NULL
问题描述
我有一个ViewModel
显示transactions
和transactionSummary
LiveData的句柄
// Transactions
val transactions: LiveData<List<Transaction>> = getTransactionByDateUseCase
.getTransactionsByDate(dateRange.startDate, dateRange.endDate)
// Transaction Summary
private var _transactionsSummary = MutableLiveData<TransactionSummary>()
val transactionsSummary: LiveData<TransactionSummary> = _transactionsSummary
transactions
来自Room的返回LiveData<T>
类似,transactionSummary
但有一个转换过程来获取事务的摘要,如income
和expense
。
下面是改造过程:
private fun getTransactionsSummary(dateRange: DateRange): LiveData<TransactionSummary> {
return Transformations.map(
getTransactionByDateUseCase.getTransactionsByDate(dateRange.startDate, dateRange.endDate)
) { data ->
getTransactionSummaryUseCase.transactions = data
val summary = getTransactionSummaryUseCase.getSummaries(dateRange)
summary
}
}
但是,当我从 Fragment 请求更新时,transactionSummary
总是返回NULL
getFetchTransactionViewModel().updateTransactionSummary(selectedDateRange)
这是我里面的更新功能ViewModel
:
fun updateTransactionSummary(dateRange: DateRange) {
_transactionsSummary.value = getTransactionsSummary(dateRange).value
}
我观察到transactionSummary
这样的:
getFetchTransactionViewModel().transactionsSummary.observe(this, Observer {
textViewIncome.text = it.totalIncome.formatCurrency(isVisibleCurrency = true)
textViewExpense.text = it.totalExpense.formatCurrency(isVisibleCurrency = true)
textViewBalance.text = (it.totalIncome - it.totalExpense).formatCurrency(isVisibleCurrency = true)
})
是否有任何遗漏的步骤或不正确的实现?
谢谢
解决方案
我自己也遇到了完全相同的问题。似乎使用 Transformations.map 创建的 LiveData 对象(通常可能还有 MediatorLiveData )仅在第一个观察者订阅它们(活动状态)后才初始化它们的值。在此之前,即使源 LiveData 有值,它也会返回值 null(非活动状态)。这发生在你的函数updateTransactionSummary()
中。
解决方案 1:您可以直接使用转换后的 LiveData,而不是尝试从中提取值并将其放入另一个 MutableLiveData。像这样的东西:
private var _transactionsSummary = getTransactionsSummary(dateRange)
val transactionsSummary: LiveData<TransactionSummary> = _transactionsSummary
然后你就不需要这个updateTransactionSummary()
功能了。
此外,您可以直接使用事务 LiveData 作为转换的源,而不是获取第二个:
private fun getTransactionsSummary(dateRange: DateRange): LiveData<TransactionSummary> {
return Transformations.map(transactions) { data ->
getTransactionSummaryUseCase.transactions = data
val summary = getTransactionSummaryUseCase.getSummaries(dateRange)
summary
}
}
解决方案 2:在您的评论中,您说您想通过另一个事件触发摘要更新。在这种情况下,使用 LiveData 转换似乎是多余的:
private fun getTransactionsSummary(dateRange: DateRange): TransactionSummary {
getTransactionSummaryUseCase.transactions = transaction.value
return getTransactionSummaryUseCase.getSummaries(dateRange)
}
fun updateTransactionSummary(dateRange: DateRange) {
_transactionsSummary.value = getTransactionsSummary(dateRange)
}
推荐阅读
- reactjs - 没有从 stylelint / stylelint-config-styled-components 得到结果或错误
- javascript - .toggleClass 在函数内部不起作用
- python - 使用 matplotlib 的 set_array() 例程的准则是什么?
- php - Twig 中的 Symfony ManyToMany 错误消息
- javascript - 为什么每个并行承诺都获得相同的值(res 总是 5 async 不工作)?
- android - 如何在 Android 中使用 FirebaseUI 检索用户的姓名和姓氏?
- java - 检查单击复选框的条件
- java - 如何在 java 中的大文件上使用 Deflater 和 Inflater?
- python - 如何在python中调整输出图像的大小?
- asp.net - ASP.NET libwebp.dll 如何将 WebP 图像保存到磁盘