Обобщенная функция, позволяющая избежать повторяемости

Я хочу иметь обобщенную функцию для моего метода репозитория, которая выполняет вызов API. Вот код -

RemoteInterface.java

interface RemoteInterface {

    @GET("...")
    suspend fun getRandomImage(): MyModel

    @GET(".../{id}/...")
    suspend fun getRandomImageById(@Path("id") id: String): MyModel
}

Теперь мой Repositoryclass выглядит так:

override suspend fun getImageFromRemote(): MyResult {
        if (util.checkDeviceInternet()) {
            try {
                val result = remoteInterface.getRandomImage()
                if (result.status == "200") {
                    return MyResult.Content(result)
                } else {
                    return MyResult.Error(MyResult.ErrorType.API_ERROR)
                }
            } catch (e: Exception) {
                return MyResult.Error(MyResult.ErrorType.API_ERROR)
            }
        } else {
            return MyResult.Error(MyResult.ErrorType.NO_INTERNET)
        }
    }

    override suspend fun getImageByIdFromRemote(id: String): MyResult {
        if (util.checkDeviceInternet()) {
            try {
                val result = remoteInterface.getRandomImageById(id)
                if (result.status == "200") {
                    return MyResult.Content(result)
                } else {
                    return MyResult.Error(MyResult.ErrorType.API_ERROR)
                }
            } catch (e: Exception) {
                return MyResult.Error(MyResult.ErrorType.API_ERROR)
            }
        } else {
            return MyResult.Error(MyResult.ErrorType.NO_INTERNET)
        }
    }

Как видите, мои 2 метода в репозитории имеют повторяющееся тело функции. Можно ли как-нибудь написать обобщенную функцию, которая выполняет те же функции, что и эти две функции?


person Ma2340    schedule 19.09.2019    source источник
comment
для этого вы должны использовать технику method overloading, см. здесь: medium.com/coding-blocks/   -  person user2342558    schedule 19.09.2019
comment
Это не то, как вы реализуете модернизацию.   -  person Kaushik Burkule    schedule 19.09.2019
comment
@KaushikBurkule Не могли бы вы объяснить мою ошибку? Было бы полезно   -  person Ma2340    schedule 19.09.2019
comment
позвольте мне подтвердить, что вы используете модифицированную библиотеку для сетевых вызовов?   -  person Kaushik Burkule    schedule 19.09.2019
comment
Да... Я использую версию 2.6.1   -  person Ma2340    schedule 19.09.2019
comment
Выпущена версия Retrofit 2.6.0 с поддержкой функций приостановки. Так что вы все делаете правильно.   -  person Kaushik Burkule    schedule 19.09.2019


Ответы (2)


Для этого можно использовать встроенную функцию с нулевыми накладными расходами.

private inline fun usefulFunction(block: () -> MyModel): MyResult {
    if (util.checkDeviceInternet()) {
        try {
            val result = block()
            if (result.status == "200") {
                return MyResult.Content(result)
            } else {
                return MyResult.Error(MyResult.ErrorType.API_ERROR)
            }
        } catch (e: Exception) {
            return MyResult.Error(MyResult.ErrorType.API_ERROR)
        }
    } else {
        return MyResult.Error(MyResult.ErrorType.NO_INTERNET)
    }
}

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

override suspend fun getImageFromRemote(): MyResult {
    return usefulFunction {
        remoteInterface.getRandomImage()
    } 
}

override suspend fun getImageByIdFromRemote(id: String): MyResult {
    return usefulFunction {
        remoteInterface.getRandomImageById(id)
    }
}
person Dominic Fischer    schedule 19.09.2019

Вы можете удалить блок try{}catch{} и заменить его блоком CoroutineExceptionHandler:

val coroutineExceptionHandler = CoroutineExceptionHandler{_,_ -> return MyResult.Error(MyResult.ErrorType.API_ERROR)
}

coroutineScope.launch(coroutineExceptionHandler ){
  val result = getImageFromRemote()
}
person coroutineDispatcher    schedule 19.09.2019