Android 上 LiveData 的并发问题



我正在尝试使用改造和LiveData操作从API中提取的数据。下面是我的代码

viewModel.getTransactions("withdrawals").observe(this, Observer {
if (it.getError() == null) {
dataAdapter = ArrayList(it.getTransaction()?.data)
if (dataAdapter.size == 0) {
// no withdrawal
withdrawSum = 0
} else {
it.getTransaction()?.data?.forEachIndexed { _, element ->
withdrawSum += Math.abs(element.attributes.amount)
}
}
} else {
// Error
}
})
viewModel.getTransactions("deposits").observe(this, Observer {
if(it.getError() == null){
dataAdapter = ArrayList(it.getTransaction()?.data)
if(dataAdapter.size == 0){
// no deposit
depositSum = 0
}else {
it.getTransaction()?.data?.forEachIndexed{ _, element ->
depositSum+=Math.abs(element.attributes.amount)
}
}
} else {
// Error
}
})
// difference will be 0 since deposit = 0 and withdrawal = 0
difference = deposit - withdrawal

我遇到的问题是这条线difference = deposit - withdrawal.这是立即调用的,而不是等待 Retrofit 调用完成再进行减法。我该怎么做才能解决这个问题?一个可怕的解决方案是将存款代码嵌套在提款it.getError() == null内,有没有更干净的解决方案?

我已经解决了这个问题。

val withdrawals = model.getTransactions("withdrawals")
val deposits = model.getTransactions("deposits")
zipLiveData(withdrawals, deposits).observe(this, Observer {
if(it.first.getError() == null){
dataAdapter = ArrayList(it.first.getTransaction()?.data)
if (dataAdapter.size == 0) {
// no withdrawal
withdrawSum = 0
}  else {
it.first.getTransaction()?.data?.forEachIndexed { _, element ->
withdrawSum += Math.abs(element.attributes.amount)
}
}
} else {
// Error
}
if(it.second.getError() == null){
dataAdapter = ArrayList(it.second.getTransaction()?.data)
if (dataAdapter.size == 0) {
// no deposit
depositSum = 0
}  else {
it.second.getTransaction()?.data?.forEachIndexed { _, element ->
depositSum += Math.abs(element.attributes.amount)
}
}
} else {
// Error
}
difference = depositSum - withdrawSum
})

函数zipLiveData取自此处

fun <A, B> zipLiveData(a: LiveData<A>, b: LiveData<B>): LiveData<Pair<A, B>> {
return MediatorLiveData<Pair<A, B>>().apply {
var lastA: A? = null
var lastB: B? = null
fun update() {
val localLastA = lastA
val localLastB = lastB
if (localLastA != null && localLastB != null)
this.value = Pair(localLastA, localLastB)
}
addSource(a) {
lastA = it
update()
}
addSource(b) {
lastB = it
update()
}
}
}