У меня есть эта функция в классе FooClass:
fun foo(id: Int, listener: Listener<JsonElement>) {
enqueue(listener, apiService.getFoo(id))
}
Это интерфейс:
interface Listener<T> {
fun onSuccess(result: T?)
fun onFailure()
}
Когда я его вызываю, я делаю так:
FooClass().foo(id, object : FooClass.Listener<JsonElement> {
override fun onSuccess(result: JsonElement?) {}
override fun onFailure() {}
})
Я хочу сделать лямбду для упрощения при вызове. Что-то вроде этого:
fun foo {id ->
// Perform onSuccess
// Perform onFailure
}
Я знаю, что это элементарно, но я запутался ... :-(
Большое спасибо за помощь.
interface Listener<T> { fun onSuccess(result: T?) fun onFailure() }
Для этого вам понадобится несколько уловок.
typealias SuccessCallback<T> = (T?) -> Unit
typealias FailureCallback = () -> Unit
inline fun FooClass.foo(id: Int, crossinline success: SuccessCallback<JsonElement?>, crossinline failure: FailureCallback) {
foo(id, object: FooClass.Listener<JsonElement> {
override fun onSuccess(result: JsonElement?) = success(result)
override fun onFailure() = failure()
})
}
Теперь вы можете вызвать
FooClass().foo(id,
success = { result: JsonElement? ->
...
},
failure = {
}
)
Технически, если у вас есть FooClass, то суть в том, что вам нужно иметь возможность предоставлять две отдельные лямбды, а не только одного слушателя. Но если у вас нет FooClass, тогда вы должен сможете использовать эту функцию расширения и можете в значительной степени использовать ее где угодно. typealiases должен быть верхнего уровня внутри файла, но вне класса. Они также могут быть private. Если функция верхнего уровня, вы можете легко импортировать ее.
Спасибо за отличное объяснение :-). У меня эта ошибка внутри развлечения: object is not abstract and does not implement abstract member. Required: Int, Found: <T>
Я был так сосредоточен на crossinline, что забыл добавить параметр id: Int. Фиксированный.
У меня есть Type mismatch ... Required FooClass.Listener<JsonElement>, но Found: <T>. Обновил вопрос ... Возможно интерфейс понадобился.
Что ж ... в любом случае, я нашел верное решение, спасибо вам. Я собираюсь это написать. :-)
Мне нужно было вернуться домой и попробовать, и да, мне действительно пришлось удалить материал T. Хотя это было довольно близко, я думаю, в вашем ответе не хватает перекрестных строк. Crossinline должен улучшить байт-код, afaik.
Да, лучше и очень красиво :-). Я собираюсь выразить это как правильный ответ.
Благодаря @EpicPandaForce я нашел решение. Вот это:
fun foo(id: Int, success: (JsonElement?) -> Unit, error: () -> Unit) {
enqueue(apiService.getFoo(id), object : Listener<JsonElement> {
override fun onSuccess(result: JsonElement?) = success(result)
override fun onFailure() = error()
})
}
Я изменил порядок параметров наenqueueфункция, чтобы быть более читаемым.
Вызвать функцию очень просто:
FooClass().foo(id,
success = { result ->
// Handle success result
},
error = {
// Handle error
}
)
Покажите, пожалуйста, определение
Listener<T>.