Как обрабатывать ошибки с liveData - PullRequest
3 голосов
/ 30 апреля 2020

В моем приложении у меня есть этот поток:

ClickListender в моем фрагменте:

  search_button.setOnClickListener {
        if(search_input.text.isNullOrEmpty())
            Toast.makeText(activity, "Input Error", Toast.LENGTH_LONG).show()
        else
            viewModel.onSearchButtonClicked(search_input.text.toString())
    }

onSearchButtonClicked внутри viewModel:

    fun onSearchButtonClicked(input: String) {
        coroutineScope.launch {
   repo.insertToDatabase(input)
        }
    }

insertToDatabase внутри Repository:

   suspend fun insertToDatabase(string: String) {
        withContext(Dispatchers.IO) {
            val dataList =
                ExternalApi.retrofitCall.getData(string).await()
            if (dataList.intialDataResult < 1) {
                //show error
            } else {
                //all good
                database.myDataBase.insertAll(dataList)
            }
        }
    }

Мне нужно показать сообщение об ошибке, если intialDataResult меньше единицы. Я думал о создании MutableLiveData внутри моего репозитория с начальным значением false и прослушивании фрагмента через viewModel, но это не очень хороший подход, потому что у меня нет способа установить LiveData в значение «false» снова после показа сообщение об ошибке.

Я также пытался вернуть bool из функции insertToDatabase и решить, показывать ошибку или нет, но безуспешно.

Есть идеи, как решить эту проблему?

1 Ответ

3 голосов
/ 30 апреля 2020

Почему бы не создать LiveData для управления состоянием результатов вашей работы?

Создать класс для хранения результата работы почему запечатанный класс?

sealed class ResultState{
    object Success: ResultState() // this is object because I added no params
    data class Failure(val message: String): ResultState()
}

Создание LiveData для отчета об этом результате

val stateLiveData = MutableLiveData<ResultState>()

Сделать insertToDatabase() вернуть результат

suspend fun insertToDatabase(input: String): ResultState {
    return withContext<ResultState>(Dispatchers.IO) {

        val dataList =
            ExternalApi.retrofitCall.getData(string).await()
        if (dataList.intialDataResult < 1) {
            return@withContext ResultState.Failure("Reason of error...")
        } else {
            database.myDataBase.insertAll(dataList)
            return@withContext ResultState.Success
        }
    }
}

Теперь, сообщить результат в пользовательский интерфейс

fun onSearchButtonClicked(input: String) {
    coroutineScope.launch {
        val resultState = repo.insertToDatabase(input)
        stateLiveData.value = resultState
    }
}

В пользовательском интерфейсе

viewModel.stateLiveData.observe(viewLifeCycleOwner, Observer { state ->

    when (state) {
        is ResultState.Success -> { /* show success in UI */ }
        is ResultState.Failure -> { /* show error in UI with state.message variable */ }
    }
})

Аналогично, вы можете добавить ResultState.PROGRESS, чтобы показать, что задача выполняется в пользовательском интерфейсе.

Если у вас есть какие-либо запросы, добавьте комментарий.

...