Android 上 LiveData 的并发问题

Concurrency issue with LiveData on Android

我正在尝试使用改造和 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取自here

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