Как создать безопасную оболочку вызова для функций Rx Java в Kotlin? - PullRequest
0 голосов
/ 26 мая 2020

Ниже вставлен фрагмент кода из приложения Google Plaid , которое обертывает функции приостановки и безопасно выполняет сетевые операции. Какие изменения необходимо внести, чтобы он работал с функциями Rx Java, а не с сопрограммами, и ждал результата сети, любая помощь приветствуется.

/**
 * Wrap a suspending API [call] in try/catch. In case an exception is thrown, a [Result.Error] is
 * created based on the [errorMessage].
 */
suspend fun <T : Any> safeApiCall(call: suspend () -> Result<T>, errorMessage: String): Result<T> {
    return try {
        call()
    } catch (e: Exception) {
        // An exception was thrown when calling the API so we're converting this to an IOException
        Result.Error(IOException(errorMessage, e))
    }
}

Пример использования в ProductHuntRemoteDataSource.kt:

class ProductHuntRemoteDataSource @Inject constructor(private val service: ProductHuntService) {

    /**
     * Load Product Hunt data for a specific page.
     */
    suspend fun loadData(page: Int) = safeApiCall(
            call = { requestData(page) },
            errorMessage = "Error loading ProductHunt data"
    )

    private suspend fun requestData(page: Int): Result<GetPostsResponse> {
        val response = service.getPostsAsync(page)
        if (response.isSuccessful) {
            val body = response.body()
            if (body != null) {
                return Result.Success(body)
            }
        }
        return Result.Error(IOException("Error loading ProductHunt data " +
                "${response.code()} ${response.message()}"))
    }
}

1 Ответ

2 голосов
/ 26 мая 2020

Вы можете легко выполнить эту работу с Rx Java, преобразовав ваши наблюдаемые в функции приостановки с помощью функций расширения awaitFirst() или await() (для Single). Вам нужно использовать расширения Rx Java.

Edit:

вы можете написать функцию расширения для своих наблюдаемых, чтобы сделать что-то похожее, но не идентичное.

Вот возможное решение

fun <T> Observable<Result<T>>.safeCall(errorMessage: String, block: (Result<T>) -> Unit): Disposable =
    subscribe({ response: Result<T> ->
        if (response.isSuccess && response.body != null) {
            block(Result.Success(response.body))
        } else {
            block(Result.Error(IOException(errorMessage)))
        }
    }, { throwable ->
        block(Result.Error(IOException(errorMessage, throwable)))
    })

вы бы назвали это на наблюдаемом, как это

val disposable = myObservable.safeCall("Error message") { result ->
    // TODO: handle result
}
...