Skip to content

Instantly share code, notes, and snippets.

@olddustysocksunderthecouch
Last active April 23, 2019 08:28
Show Gist options
  • Save olddustysocksunderthecouch/2386ede2f7badba6f94d38b030e6fa73 to your computer and use it in GitHub Desktop.
Save olddustysocksunderthecouch/2386ede2f7badba6f94d38b030e6fa73 to your computer and use it in GitHub Desktop.
Kotlin Extensions for Livedata
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