#android #kotlin #generics #variadic-functions
#Android #kotlin #общие сведения #переменные функции
Вопрос:
Мой вопрос в том, можно ли сделать что-то вроде:
fun <T, R> someFunction(vararg sources<out T>, doSomething: (vararg sources<out T>) -> R) {
// do something here
}
Итак, если я сделаю что-то вроде:
someFunction(SomeType<A>(), SomeType<B>(), SomeType<C>()) { a: A, b: B c: C ->
// do Something
}
В принципе, функция более высокого порядка должна требовать все типы параметров.
Причина, по которой я спрашиваю об этом, заключается в том, что я хотел бы упростить код, подобный этому:
inline fun <T1, T2, R> MediatorLiveData<out R>.merge(source1: LiveData<out T1>, source2: LiveData<out T2>, crossinline merger: (T1?, T2?) -> R?) {
addSource(source1) {
this.value = merger.invoke(source1.value, source2.value)
}
addSource(source2) {
this.value = merger.invoke(source1.value, source2.value)
}
}
inline fun <T1, T2, T3, R> MediatorLiveData<out R>.merge(source1: LiveData<out T1>, source2: LiveData<out T2>, source3: LiveData<out T3>, crossinline merger: (T1?, T2?, T3?) -> R?) {
addSource(source1) {
this.value = merger.invoke(source1.value, source2.value, source3.value)
}
addSource(source2) {
this.value = merger.invoke(source1.value, source2.value, source3.value)
}
addSource(source3) {
this.value = merger.invoke(source1.value, source2.value, source3.value)
}
}
inline fun <T1, T2, T3, T4, R> MediatorLiveData<out R>.merge(source1: LiveData<out T1>, source2: LiveData<out T2>, source3: LiveData<out T3>, source4: LiveData<out T4>, crossinline merger: (T1?, T2?, T3?, T4?) -> R?) {
addSource(source1) {
this.value = merger.invoke(source1.value, source2.value, source3.value, source4.value)
}
addSource(source2) {
this.value = merger.invoke(source1.value, source2.value, source3.value, source4.value)
}
addSource(source3) {
this.value = merger.invoke(source1.value, source2.value, source3.value, source4.value)
}
addSource(source4) {
this.value = merger.invoke(source1.value, source2.value, source3.value, source4.value)
}
}
Кто-нибудь может что-нибудь предложить? Заранее спасибо!
Ответ №1:
Попробуйте следующую функцию:
fun <T, R> someFunction(vararg sources: LiveData<out T>, doSomething: (sources: Array<out LiveData<out T>>) -> R) {
// ...
doSomething(sources)
}
Кажется, мы не можем использовать модификатор vararg
в лямбда-выражении doSomething
, замена его на Array
сработает.
РЕДАКТИРОВАТЬ: Таким образом, в принципе, вы сможете сделать что-то вроде следующего для разного количества источников без создания дополнительных функций, как в вашем примере:
fun <T, R> someFunction(vararg sources: LiveData<out T>, doSomething: (sources: Array<out LiveData<out T>>) -> R) {
sources.forEach {
addSource(it) {
doSomething.invoke(sources)
}
}
}
// Call someFunction with different number of args:
val l1: LiveData<Int> = MutableLiveData()
val l2: LiveData<String> = MutableLiveData()
val l3: LiveData<String> = MutableLiveData()
// Call with two args:
someFunction(l1, l2) { sources: Array<out LiveData<out Any>> ->
val data1 = sources[0] as LiveData<Int>
val data2 = sources[1] as LiveData<String>
// do your work here
}
// Or Call with three args:
someFunction(l1, l2, l3) { sources: Array<out LiveData<out Any>> ->
val data1 = sources[0] as LiveData<Int>
val data2 = sources[1] as LiveData<String>
val data3 = sources[2] as LiveData<String>
// do your work here
}
Комментарии:
1. Я не понимаю, можете ли вы объяснить это дальше? Как это может упростить мои методы, описанные выше?
2. будет ли это работать для разных типов. Нравится
someFunction(liveDataOfString, liveDataOfInteger)
и это приведет к тому, чтоsomeFunction(liveDataOfString, liveDataOfInteger) { someString, someInteger -> // do something here }
?3. Да, это будет работать для разных типов. Но лямбда-выражение будет выглядеть следующим образом:
someFunction(l1, l2, l3) { sources: Array<out LiveData<out Any>> -> ... }
4. Пожалуйста, посмотрите мои правки. Если я правильно понял, вам нужно просто привести его к соответствующему типу, например: ` val data1 = sources[0] как LiveData<Int>`
5. Я тоже так думаю. Я просто надеялся, что может быть какой-то другой способ. В любом случае, я отмечу ваш ответ сейчас. Большое вам спасибо!