Возвращение LiveData из метода RxJava .Zip внутри функции - PullRequest
0 голосов
/ 30 марта 2019

Я выполняю рефакторинг репозитория с LiveData объектами экземпляра в направлении Репозитория , который возвращает LiveData из функций Репозитария в соответствии случшие практики из выступления на Саммите разработчиков Android в 2018 году, Развлечения с LiveData (Android Dev Summit '18) и сообщение в блоге разработчиков Android, LiveData за пределами ViewModel - Реактивные шаблоны с использованием Transformations и MediatorLiveData .

Наблюдаемый

При попытке вернуть объект MutableLiveData в Репозиторий из метода, использующего функцию Observable.zip, значение MutableLiveData равноnull.

Ожидается

Возврат объекта MutableLiveData из функции в Репозиторий метод с использованием функции Observable.zip, которую можно наблюдать с помощью ViewModel и Фрагмент / Активность .

Оригинальный код

Шаги

  1. Хранилище 1045 * вызывается в onCreate() фрагмента 1048 *.
  2. getPrices() извлекает последние данные о ценах с сервера.
  3. Для каждой части новых данных, извлекаемых с сервера, метод parsePriceData() форматирует данные должным образом изаполняет экземпляр MutableLiveData object graphLiveData.

    object PriceRepository {
    var graphLiveData = MutableLiveData<HashMap<Exchange, PriceGraphData>>()
    
    fun getPrices(isRealtime: Boolean, isOnCreateCall: Boolean, timeframe: Timeframe) {
        listenerRegistration = contentEthBtcCollection
                .orderBy(TIMESTAMP, Query.Direction.ASCENDING)
                .whereGreaterThan(TIMESTAMP, getTimeframe(timeframe))
                .addSnapshotListener(EventListener { value, error ->
                    error?.run {
                        Log.e(LOG_TAG, "Price Data EventListener Failed.", error)
                        return@EventListener
                    }
                    parsePriceData(value!!.documentChanges)
                })
    }
    
    private fun parsePriceData(documentChanges: List<DocumentChange>) {
        for (priceDataDocument in documentChanges) {
            val priceData = priceDataDocument.document
                .toObject(MaximumPercentPriceDifference::class.java)
        compositeDisposable.add(zip(
                    generateGraphData(GRAPH_ONE, priceData.graphOneData).subscribeOn(io()),
                    generateGraphData(GRAPH_TWO, priceData.graphTwoData).subscribeOn(io()),
                    generateGraphData(GRAPH_THREE, priceData.graphThreeData).subscribeOn(io()),
                    generateGraphData(GRAPH_FOUR, priceData.graphFourData).subscribeOn(io()),
                    getFunction4())
                    .subscribeOn(io())
                    .observeOn(mainThread())
                    .subscribeWith(object : DisposableObserver<List<HashMap<Exchange, PriceGraphData>>>() {
                        override fun onNext(priceGraphDataList: List<HashMap<Exchange, PriceGraphData>>) {
                            priceGraphDataList.all {
                                // Working as expected.
                                graphLiveData.postValue(it)
                                true
                            }
                        }
    
                        override fun onError(e: Throwable) {
                            e.printStackTrace()
                        }
    
                        override fun onComplete() {
                            compositeDisposable.clear()
                        }
                    }))
        }
    }
    }
    

Refactored Code

Шаги

Шаги 1-3 одинаковы, за исключениемна шаге 3 вместо сохранения значений в объекте экземпляра MutableLiveData экземпляра значения сохраняются в объекте MutableLiveData в методе.

object PriceRepository {

    fun getPrices(isRealtime: Boolean, isOnCreateCall: Boolean, timeframe: Timeframe) {
            contentEthBtcCollection
                    .orderBy(TIMESTAMP, Query.Direction.ASCENDING)
                    .whereGreaterThan(TIMESTAMP, getTimeframe(timeframe))
                    .get()
                    .addOnCompleteListener {
                        // This value is null. Thus the LiveData is not being returned properly in the 'parsePriceData' method.
                        val priceLiveData = parsePriceData(it.result!!.documentChanges)
                    }
        }
    }

    private fun parsePriceData(documentChanges: List<DocumentChange>): LiveData<HashMap<Exchange, PriceGraphData>> {
        val graphLiveData = MutableLiveData<HashMap<Exchange, PriceGraphData>>()
        for (priceDataDocument in documentChanges) {
            val priceData = priceDataDocument.document
                    .toObject(MaximumPercentPriceDifference::class.java)
        //TODO: Refactor axis to use dates.
        compositeDisposable.add(zip(
                    generateGraphData(GRAPH_ONE, priceData.graphOneData).subscribeOn(io()),
                    generateGraphData(GRAPH_TWO, priceData.graphTwoData).subscribeOn(io()),
                    generateGraphData(GRAPH_THREE, priceData.graphThreeData).subscribeOn(io()),
                    generateGraphData(GRAPH_FOUR, priceData.graphFourData).subscribeOn(io()),
                getFunction4())
                .subscribeOn(io())
                    .observeOn(mainThread())
                    .subscribeWith(object : DisposableObserver<List<HashMap<Exchange, PriceGraphData>>>() {
                        override fun onNext(priceGraphDataList: List<HashMap<Exchange, PriceGraphData>>) {
                            priceGraphDataList.all {
                                // Data returned here as expected, but LiveData object `graphLiveData.value` is returning null for the method.
                                graphLiveData.postValue(it)
                                true
                            }
                        }

                        override fun onError(e: Throwable) {
                            e.printStackTrace()
                        }

                        override fun onComplete() {
                            compositeDisposable.clear()
                        }
                    }))
        }
        return graphLiveData
    }
}

Потенциальное решение

Проблема возникает из-за метода Observable.zip, который возвращает данные асинхронно, а не синхронно.Замена логики Observable.zip на MediatorLiveData для обработки множественных вариаций графиков позволит вернуть объект LiveData.Однако это требует рефакторинга серверной службы, чтобы упростить обработку данных для правильной работы с MediatorLiveData.Поэтому в краткосрочной перспективе я ищу обходной путь с Observable.zip.

...