Как повторить вызов API в интерфейсе дооснащения с включенными сопрограммами

#android #kotlin #retrofit2 #kotlin-coroutines

Вопрос:

У меня есть вариант использования всякий раз, когда в вызове API возникает общая ошибка, такая как потеря Интернета или неизвестная ошибка, необходимо отобразить пользовательский интерфейс ошибки с кнопкой повтора. когда пользователь нажимает кнопку повторить ранее неудачную попытку, API должен вызвать и возобновить поток пользователей.

Интерфейс API перед переносом метода сопрограмм:

  interface TodoService {
    @POST("todo/create")
   fun createTodo(@Body request: TodoRequest): Call<TodoResponse>
}
 

Клиент API:

     fun <T> fetch(call: Call<T>, completion: (result: NetworkBoundResource<T>) -> Unit) {
   
    call.enqueue(object : Callback<T> {
        override fun onFailure(call: Call<T>, t: Throwable) {
            // I have the mechanism save call object and completion and show error UI
            // when user press retry fetch(call.clone(), completion
        }

        override fun onResponse(call: Call<T>, response: Response<T>) {

        }
    })
}
 

Это не было проблемой до переноса интерфейса дооснащения на методы приостановки сопрограмм. Потому что я могу просто клонировать объект вызова модернизации (call.clone()) и повторить вызов API, как описано в комментариях к коду.

Интерфейс API после переноса метода сопрограмм:

 interface TodoService {
   @POST("todo/create")
   suspend fun createTodo(@Body request: TodoRequest): TodoResponse
}
 

Теперь, как я могу получить ту же функцию без объекта вызова?

Ответ №1:

Вы можете выполнить повторную попытку, сохранив действие за пределами задания сопрограммы, например, добавив отправку на кнопку.

Вот простой пример, но не завершенный:

 class ViewModel {

    val context = CoroutineScope(Dispatchers.Main)
    var dispatchRetry: (() -> Unit)? = null

    fun createTodo(requestData: TodoRequest) {
        context.launch() {
            try {
                todoService.createTodo(requestData)
            } catch (t: Throwable) {
                dispatchRetry = { todoService.createTodo(requestData) }
            }
        }
    }

    fun retry() {
        dispatchRetry?.invoke()
    }
}
 

Комментарии:

1. это решение полезно. но мне приходится справляться с каждой моделью представления. таким образом, решение не является масштабируемым.

2. Если у вас есть только несколько запросов, я бы выбрал не обобщенное решение (следуйте за ПОЦЕЛУЕМ). Но вы также можете создать свою собственную оболочку, которая обрабатывает каждое выполнение сопрограммы с помощью повторной попытки.

Ответ №2:

используйте репозитории и модель просмотра, чтобы получать ответы через текущие данные с помощью сопрограмм, а затем в вашей активности наблюдатели за пользователями, чтобы узнать дату. это лучший способ использовать сопрограммы, а также лучшая практика для MVVM

Комментарии:

1. Я следую шаблону репозитория. Похоже, ты не понял моего вопроса. Я не использую вызов дооснащения<T>, потому что в этом нет необходимости, если вы приостанавливаете. теперь, как вы повторите попытку ?