Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Extension functions for LiveData

Extension functions for LiveData

Yumemi.apk #1 ( https://yumemi.connpass.com/event/180842/ ) の資料

Hiroyuki Kusu

August 21, 2020
Tweet

More Decks by Hiroyuki Kusu

Other Decks in Programming

Transcript

  1. ViewModel தͷ LiveData ͷهड़ private val _liveData1: MutableLiveData<Int> = MutableLiveData()

    val liveData1: LiveData<Int> = _liveData1 val liveData2: LiveData<Boolean> = liveData1.map { // ... } "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0" • σʔλͷؔ࿈ੑ͕એݴతʹఆٛ͞Ε͍ͯΔͱ෼͔Γ΍͍͢ • ΋ͬͱศརʹ͍ͨ͠..! • ࣗલͰ࡞੒֦ͨ͠ுؔ਺Λɺ͍͔ͭ͘঺հ͠·͢
  2. fun <T, U> LiveData<T>.coMap( coroutineScope: CoroutineScope, coroutineContext: CoroutineContext = coroutineScope.coroutineContext,

    block: suspend (T) -> U ): LiveData<U> { val result = MediatorLiveData<U>() result.addSource(this) { coroutineScope.launch(coroutineContext) { result.postValue(block.invoke(it)) } } return result } ※ switchMap() ͱ livedata {} Λ૊Έ߹Θͤͯ΋ಉ͜͡ͱ͕Ͱ͖·͢ ※ ݱঢ়Ͱ͸ inline fun ʹ͢ΔͱམͪΔ https://github.com/Kotlin/kotlinx.coroutines/issues/ coMap val liveData2: LiveData<List<SampleItem>> = liveData1.coMap(viewModelScope) { it: Int delay(3_000) sampleRepository.getItemList(it) // suspending function } ར༻Πϝʔδ ؔ਺ͷఆٛ
  3. val liveData3: LiveData<String> = merge(liveData1, liveData2) { i: Int?, b:

    Boolean? -> // ... } inline fun <T1, T2, U> merge( liveData1: LiveData<T1>, liveData2: LiveData<T2>, crossinline block: (T1?, T2?) -> U? ): LiveData<U> { val result = MediatorLiveData<U>() result.addSource(liveData1) { t1 -> block.invoke(t1, liveData2.value)?.takeUnless { it is Unit }?.let { result.value = it } } result.addSource(liveData2) { t2 -> block.invoke(liveData1.value, t2)?.takeUnless { it is Unit }?.let { result.value = it } } return result } merge ར༻Πϝʔδ ؔ਺ͷఆٛ (֦ுؔ਺Ͱͳ͘ී௨ͷؔ਺) block தͰ LiveDataͷߋ৽ΛΩϟϯηϧͰ͖ΔΑ͏ʹ͢Δҝͷॲஔ (Ωϟϯηϧ͍ͨ͠৔߹͸null΋͘͠͸໭Γ஋ͳ͠Ͱreturn͢Δ)
  4. val liveData2: LiveData<Int> = liveData1.filter { 100 < it }

    inline fun <T> LiveData<T>.filter( crossinline block: (T) -> Boolean ): LiveData<T> { val result = MediatorLiveData<T>() result.addSource(this) { if (block.invoke(it)) { result.value = it } } return result } filter ར༻Πϝʔδ ؔ਺ͷఆٛ
  5. val liveData2: LiveData<Int> = liveData1.map { // ... }.coMap(viewModelScope) {

    // ... }.map { // ... }.coMap(viewModelScope) { // ... }.filter { // ... } ͭͳ͛ͯॻ͚Δ
  6. val observe = liveData1.map { }.observe() // ... override fun

    onCleared() { observe.cancel() } class Observe<T>(private val liveData: LiveData<T>) { private val observer = Observer<T> {} fun start() { liveData.observeForever(observer) } fun cancel() { liveData.removeObserver(observer) } } fun <T> LiveData<T>.observe(): Observe<T> = Observe(this).apply { start() } observe ViewModel ͷഁغ࣌ʹ͸؍ଌΛऴྃͤ͞Δඞཁ observeForever Λར༻ ͜ͷϒϩοΫͰ೚ҙͷॲཧ ؔ਺ͷఆٛ ར༻Πϝʔδ