Generics и MutableLiveData в Котлине - PullRequest
1 голос
/ 31 октября 2019

У меня есть две очень похожие функции, и я пытаюсь избежать дублирования в моем коде с помощью обобщений. Функции имеют блок try catch и уведомляют своих наблюдателей двумя MutableLiveData двух разных типов:

val noWasteRecipesPosts: MutableLiveData<List<Recipe>> = MutableLiveData()
val lastArticlesPosts: MutableLiveData<List<Article>> = MutableLiveData()

fun getNoWasteRecipesPosts() {
        makeCall(service.getRecipes(), noWasteRecipesPosts)
        scope.launch {
            try {
                val response = service.getRecipes().await()
                when (response.isSuccessful) {
                    true -> {
                        response.body()?.let {
                            noWasteRecipesPosts.postValue(ArrayList(response.body()))
                        } ?: run {
                            errorLiveData.postValue(response.message())
                        }
                    }
                    false -> errorLiveData.postValue(response.message())
                }
            } catch (e: Exception) {
                noConnectionLiveData.postValue(true)
            }
        }
    }

    fun getLastArticlesPosts(excludeRecipes: Boolean) {
        scope.launch {
            try {
                val response = when (excludeRecipes) {
                    true -> service.getLastArticles(categoriesToExclude = arrayListOf(BlogCategories.NO_WASTE_RECIPES.id))
                        .await()
                    false -> service.getLastArticles()
                        .await()
                }

                when (response.isSuccessful) {
                    true -> {
                        response.body()?.let {
                            lastArticlesPosts.postValue(ArrayList(response.body()))
                        } ?: run {
                            errorLiveData.postValue(response.message())
                        }
                    }
                    false -> errorLiveData.postValue(response.message())
                }
            } catch (e: Exception) {
                noConnectionLiveData.postValue(true)
            }
        }
    }

Чтобы избежать повторения кода, я пытаюсь использовать обобщения, но, вероятно, неправильно. Я определил функцию, которая принимает ответ Deferred api в качестве первого параметра, и я хотел бы передать MutableLiveData для уведомления наблюдателей в качестве второго параметра:

fun makeCall(function: Deferred<Response<*>>, successLiveData: MutableLiveData<*>) {
        scope.launch {
            try {
                val response = function.await()
                when (response.isSuccessful) {
                    true -> {
                        response.body()?.let {
                            successLiveData.postValue(it) // Compile error here
                        } ?: run {
                            errorLiveData.postValue(response.message())
                        }
                    }
                    false -> errorLiveData.postValue(response.message())
                }
            } catch (e: Exception) {
                noConnectionLiveData.postValue(true)
            }
        }

    }

К сожалению, я что-то упустил, а среда IDEвыдает ошибку несоответствия типов при попытке опубликовать значение LiveData:

несоответствие типов: обязательно: ничего! Найдено: Любое.

Я совершенно сбит с толку, есть ли у вас какие-либо предложения по поводу MutableLiveData и Generics в kotlin?

1 Ответ

2 голосов
/ 01 ноября 2019

Тип response.body() и тип MutableLiveData должны совпадать. Подпись функции должна выглядеть примерно так:

fun <T> makeCall(function: Deferred<Response<T>>, successLiveData: MutableLiveData<T>)
...