【问题标题】:Observing Android LiveData<T> from ViewModel Return NULL从 ViewModel 观察 Android LiveData<T> 返回 NULL
【发布时间】:2020-06-27 13:56:38
【问题描述】:

我有一个ViewModel 处理显示transactionstransactionSummary 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&lt;T&gt;,与 transactionSummary 类似,但有一个转换过程来获取交易摘要为 incomeexpense

以下是改造过程:

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)
    })

是否有遗漏的步骤或错误的实现?

谢谢

【问题讨论】:

  • _transactionsSummary.value = getTransactionsSummary(dateRange).value map 的用途

标签: android kotlin android-livedata android-viewmodel android-livedata-transformations


【解决方案1】:

我自己也遇到了完全相同的问题。似乎使用 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)
}

【讨论】:

  • 嘿,谢谢。非常感谢您的帮助。但我想知道,我如何告诉ViewModel 根据View 触发的事件更新transactionsSummary?因为我创建了updateTransactionSummary() 来处理这些事件。
  • @fanjavaid,我在答案中添加了解决方案 2 以支持该用例。
【解决方案2】:
fun updateTransactionSummary(dateRange: DateRange) {
    _transactionsSummary.value = getTransactionsSummary(dateRange).value
}

这不是使用 LiveData 的正确方式。

DateRange 也是一个可变参数,必须作为输入传播到异步数据加载。

这意味着它必须包含在MutableLiveData&lt;DateRange&gt; 中,然后.switchMap'd 到正确的查询结果中。

// Transaction Summary
//private var _transactionsSummary = MutableLiveData<TransactionSummary>()

private val dateRange = MutableLiveData<DateRange>()

val transactionsSummary: LiveData<TransactionSummary> = dateRange.switchMap { date ->
    getTransactionsSummary(dateRange)
}

很有可能DateRange不应该在进程死亡时被遗忘,在这种情况下,如果DateRange实际上是ParcelableSerializable,那么它应该使用SavedStateHandle自动持久化到Bundle ViewModel,如果可能的话,使用private val dateRange = savedStateHandle.getLiveData&lt;DateRange&gt;("dateRange")

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-10
    • 2020-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多