LiveData возвращает неправильный объект - PullRequest
0 голосов
/ 14 июля 2020

Я добавил Hilt в свой проект, и теперь LiveData возвращает неверный Object type. Возможно, я сделал какие-то неправильные изменения в своем коде. getAllCurrencies возвращает LiveData<Resource<Unit>>, но должно LiveData<Resource<Currencies>>

ViewModel:

class SplashScreenViewModel @ViewModelInject constructor(
private val roomDatabaseRepository: RoomDatabaseRepository,
private val retrofitRepository: RetrofitRepository) : ViewModel() {

fun getAllCurrencies(mainCurrency: String) = liveData(Dispatchers.IO) {
       emit(Resource.loading(data = null))
        try {
            emit(Resource.success(data = retrofitRepository.getAllCurrencies(mainCurrency)))
        } catch (exception: Exception) {
            emit(Resource.error(data = null, message = exception.message ?: "Error Occurred!"))
        }
    }

Репозиторий: (возвращает хороший тип)

class RetrofitRepository @Inject constructor(val currenciesApiHelper: CurrenciesApiHelper) {

suspend fun getAllCurrencies(mainCurrency: String) {
  currenciesApiHelper.getAllCurrencies(mainCurrency)
}

1 Ответ

0 голосов
/ 14 июля 2020

Вы должны return currenciesApiHelper.getAllCurrencies(mainCurrency) в репозитории.

(необязательно) Я делаю это с помощью MVVM.

Я предполагаю, что у вас есть Currency как модель, объявленная где-то уже.

Статус

sealed class Status<out T> {
    class Loading<out T> : Status<T>()
    data class Success<out T>(val data: T) : Status<T>()
    data class Failure<out T>(val exception: Exception) : Status<T>()
}

Фрагмент / Уровень презентации

viewModel.fetchCurrencies(mainCurrency)
            .observe(viewLifecycleOwner, Observer { result ->
                when (result) {
                    is Status.Loading<*> -> {
                        //display a ProgressBar or so
                    }

                    is Status.Success<*> -> {
                        //Status.Success<*> can also be Status.Success<ArrayList<Currency>>
                        //hide the ProgressBar
                        val currencies = result.data as ArrayList<Currency> 
                    }

                    is Status.Failure<*> -> {
                        //log the exception
                    }
                }
            })

ViewModel

private val repo = Repository()

@ExperimentalCoroutinesApi
    fun fetchCurrencies(mainCurrency: String): LiveData<Status<MutableList<Currency>>> =
        liveData(Dispatchers.IO) {
            emit(Status.Loading())

            try {
                repo.getCurrencies(mainCurrency).collect {
                    emit(it)
                }

            } catch (e: Exception) {
                emit(Status.Failure(e))
                Log.e("ERROR:", e.message!!)
            }
        }

Репозиторий (один источник данных)

Вместо этого здесь используется Firestore, поскольку я не уверен на 100% в правильности вашего пути.

Сделайте что должен сделать retrofitRepository.getAllCurrencies(mainCurrency), а затем предложить результат.

private val fs: FirebaseFirestore = Firebase.firestore

@ExperimentalCoroutinesApi
    fun getCurrencies(mainCurrency: String): Flow<Status<MutableList<Currency>>> = callbackFlow {

        val subscription = fs.collection("currencies")
            .addSnapshotListener { snapshot, _ ->
                if (snapshot != null) {
                    val result = snapshot.toObjects(Currency::class.java)
                    offer(Success(result))
                }
            }

        awaitClose { subscription.remove() }
    }

Между прочим, использование сопрограмм довольно приятно. Посмотрите здесь:

Изучите расширенные сопрограммы с Kotlin Flow и LiveData

Android Сопрограммы: как управлять асинхронными c задачами в Kotlin

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...