1

I am trying to manipulate the data pulled from an API using retrofit and LiveData. Below is my code

  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

What I am having issue is with this line difference = deposit - withdrawal. This is called immediately as opposed to waiting for Retrofit calls to complete before doing subtraction. What can i do to solve this issue? A horrible solution would be to nest the deposit code inside withdrawal's it.getError() == null, is there a cleaner solution?

Daniel Quah
  • 11
  • 1
  • 5

1 Answers1

0

I have solved the issue.

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

The function zipLiveData is taken from 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()
        }
    }
}
Daniel Quah
  • 11
  • 1
  • 5