Запутался в обработке ошибок на сетевом уровне при реализации MVVM в Android. Как уведомить пользователя, что-то не так? - PullRequest
2 голосов
/ 27 июня 2019

Последние пару месяцев я боролся с паттернами MVVM и компонентами android-архитектура-компонентов. В моем последнем проекте, хотя я пытался отделить часть логики приложения, но это закончилось большим количеством беспорядка кода. Каждый фрагмент проделал большую работу, от обработки пользовательского интерфейса до обработки сетевых запросов и ... В этом новом приложении я следовал рекомендациям по архитектуре приложений для Android, и до сих пор все идет хорошо. Но дело в том, что я не знаю, как обрабатывать сетевые ошибки, и я не понимаю, как я должен уведомлять пользователя, если некоторые сетевые вызовы не выполняются.

После поиска и прочтения некоторых сообщений в блоге я получил следующие функции кода (SafeApiCall и SafeApiResutl) для обработки сетевых запросов в одном месте, но дело в том, что все мои сетевые запросы выполняются с использованием модернизации и класса NetworkDataSource. Затем Я передаю NetworkDataSource и Dao классу RepositoryImpl, который является реализацией моего интерфейса репозитория. затем я передаю репозиторий в viewModel, так что ViewModel ничего не знает о сети, дао или о чем-либо еще. Итак, вот проблема, как я могу уведомить пользователя в случае каких-либо сетевых ошибок? Я думал о создании LiveData <> и передаче ему ошибок на сетевом уровне, но в этом случае репозиторий должен соблюдать это, а также, скажем, создать LiveData в репозитории, чтобы viewModel наблюдал это и так далее ... Но это слишком много цепочки, мне не нравится идея сделать это. Я также взглянул на проект GoogleSamples Todo-MVVM-live-kotlin, но, честно говоря, я не понял, что происходит.


    suspend fun <T : Any> safeApiCall(call: suspend () -> Response<BasicResponse<T>>, errorMessage: String): T? {
        return when (val result = safeApiResult(call)) {
            is NetworkResult.Success -> {
                Timber.tag("safeApiCall").d("data is ${result.serverResponse.data}")
                result.serverResponse.data
            }
            is NetworkResult.Error -> {
                Timber.tag("SafeApiCall").e("$errorMessage & Exception - ${result.exception}")
                null
            }
            else -> TODO()
        }
    }


    private suspend fun <T : Any> safeApiResult(
        call: suspend () -> Response<BasicResponse<T>>
    ): NetworkResult<T> {
        return try {
            val response = call.invoke()
            Timber.tag("SafeApiResult")
                .d("response code : ${response.code()}, server value : ${response.body()!!.status}, server message: ${response.body()!!.message}")
            if (response.isSuccessful) {
                return when (ServerResponseStatus.fromValue(response.body()!!.status)) {
                    ServerResponseStatus.SUCCESS -> NetworkResult.Success(response.body()!!)
                    ServerResponseStatus.FAILED -> TODO()
                    ServerResponseStatus.UNKNOWN -> TODO()
                }
            } else {
                TODO()
            }
        } catch (exception: Exception) {
            Timber.tag("SafeApiResultFailed").e(exception)
            NetworkResult.Error(exception)
        }

    }


    sealed class NetworkResult<out T : Any> {
        data class Success<out T : Any>(val serverResponse: BasicResponse<out T>) : NetworkResult<T>()
        data class Error(val exception: Exception) : NetworkResult<Nothing>()
    }

1 Ответ

0 голосов
/ 27 июня 2019

Вы находитесь на правильном пути.Я бы поместил оба метода в NetworkDataSource.Все выполняемые вызовы должны вызывать эти методы для обработки ошибок.

NetworkDataSource вернет NetworkResult в хранилище и вернет результат в ViewModel.

Как вы говоритевы можете использовать LiveData для уведомления об активности / фрагменте.Вы можете создать класс данных об ошибках:

data class ErrorDialog(
   val title: String, 
   val message: String
) 

и объявить LiveData<ErrorDialog>, который будет наблюдаться с вашей точки зрения.Затем, когда вы получаете уведомления в своем представлении, вы можете реализовать логику в BaseActivity / BaseFragment, чтобы показать Dialog или Toast или любой другой тип представления, чтобы указать на ошибку.

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