Last active
April 23, 2019 08:28
-
-
Save olddustysocksunderthecouch/2386ede2f7badba6f94d38b030e6fa73 to your computer and use it in GitHub Desktop.
Kotlin Extensions for Livedata
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import androidx.lifecycle.* | |
import io.reactivex.Flowable | |
/** | |
* Description: | |
* Observe LiveData with LifecycleOwner. | |
* Usage: | |
* observe(viewModel.liveData) { | |
* it ?: return@observe | |
* if (it) { | |
* // ... | |
* } | |
* } | |
*/ | |
fun <T : Any, L : LiveData<T>> LifecycleOwner.observe(liveData: L, body: (T?) -> Unit) { | |
liveData.observe(this, Observer(body)) | |
} | |
/** | |
* Description: | |
* Observe LiveData with Lifecycle owner only ONCE. | |
* Usage: | |
* observeOnce(viewModel.liveData) { | |
* it ?: return@observeOnce | |
* if (it) { | |
* // ... | |
* } | |
* } | |
*/ | |
fun <T : Any, L : LiveData<T>?> LifecycleOwner.observeOnce(liveData: L, observer: Observer<T>) { | |
liveData?.observe(this, object : Observer<T> { | |
override fun onChanged(t: T?) { | |
observer.onChanged(t) | |
liveData.removeObserver(this) | |
} | |
}) | |
} | |
/** | |
* Description: | |
* Observe MutableLiveData with LifecycleOwner. | |
* Usage: | |
* observeMutable(viewModel.liveData) { | |
* it ?: return@observeMutable | |
* if (it) { | |
* // ... | |
* } | |
* } | |
*/ | |
fun <T : Any, L : MutableLiveData<T>?> LifecycleOwner.observeMutable(liveData: L, body: (T?) -> Unit) { | |
liveData?.observe(this, Observer(body)) | |
} | |
/** | |
* Description: | |
* Observe MutableLiveData with LifecycleOwner only ONCE. | |
* Usage: | |
* observeMutableOnce(viewModel.liveData) { | |
* it ?: return@observeMutableOnce | |
* if (it) { | |
* // ... | |
* } | |
* } | |
*/ | |
fun <T : Any, L : MutableLiveData<T>?> LifecycleOwner.observeMutableOnce(liveData: L, observer: Observer<T>) { | |
liveData?.observe(this, object : Observer<T> { | |
override fun onChanged(t: T?) { | |
observer.onChanged(t) | |
liveData.removeObserver(this) | |
} | |
}) | |
} | |
/** | |
* Description: | |
* Combines to MutableLiveData objects and outputs a pair. | |
* Usage: | |
* // In the ViewModel. The type is inferred but is shown below for illustrative purposes. | |
* val combinedMutableLiveData: MutableLiveData<Pair<String, String>> = liveDataA.combineLatest(liveDataB) | |
* | |
* // Example of usage in your activity/fragment etc. | |
* observeMutable(viewModel.combinedMutableLiveData) { | |
* it ?: return@observeMutable | |
* val data: String = if (it.first.isNotEmpty()){ it.first + ", " + it.second } else it.second | |
* // ... | |
* } | |
*/ | |
fun <A, B> MutableLiveData<A>.combineLatest(b: MutableLiveData<B>): MutableLiveData<Pair<A, B>> { | |
return MediatorLiveData<Pair<A, B>>().apply { | |
var lastA: A? = null | |
var lastB: B? = null | |
addSource(this@combineLatest) { | |
if (it == null && value != null) value = null | |
lastA = it | |
if (lastA != null && lastB != null) value = lastA!! to lastB!! | |
} | |
addSource(b) { | |
if (it == null && value != null) value = null | |
lastB = it | |
if (lastA != null && lastB != null) value = lastA!! to lastB!! | |
} | |
} | |
} | |
fun <A, B, C> combineLatest(a: LiveData<A>, b: LiveData<B>, c: LiveData<C>): LiveData<Triple<A?, B?, C?>> { | |
fun Triple<A?, B?, C?>?.copyWithFirst(first: A?): Triple<A?, B?, C?> { | |
if (this@copyWithFirst == null) return Triple<A?, B?, C?>(first, null, null) | |
return [email protected](first = first) | |
} | |
fun Triple<A?, B?, C?>?.copyWithSecond(second: B?): Triple<A?, B?, C?> { | |
if (this@copyWithSecond == null) return Triple<A?, B?, C?>(null, second, null) | |
return [email protected](second = second) | |
} | |
fun Triple<A?, B?, C?>?.copyWithThird(third: C?): Triple<A?, B?, C?> { | |
if (this@copyWithThird == null) return Triple<A?, B?, C?>(null, null, third) | |
return [email protected](third = third) | |
} | |
return MediatorLiveData<Triple<A?, B?, C?>>().apply { | |
addSource(a) { value = value.copyWithFirst(it) } | |
addSource(b) { value = value.copyWithSecond(it) } | |
addSource(c) { value = value.copyWithThird(it) } | |
} | |
} | |
/** | |
* Converts LiveData into a Flowable | |
*/ | |
fun <T> LiveData<T>.toFlowable(lifecycleOwner: LifecycleOwner) : Flowable<T> = | |
Flowable.fromPublisher(LiveDataReactiveStreams.toPublisher(lifecycleOwner, this)) | |
/** | |
* Converts a Flowable into LiveData | |
*/ | |
fun <T> Flowable<T>.toLiveData(): LiveData<T> = LiveDataReactiveStreams.fromPublisher(this) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment