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

livedata

takako-fire
February 28, 2019
240

 livedata

takako-fire

February 28, 2019
Tweet

Transcript

  1. LiveData internal class CurryLiveData( private val searchWord: String, private val

    curryReadOnlyRepository: CurryReadOnlyRepository ) : LiveData<List<Curry>>() { override fun onActive() { super.onActive() curryReadOnlyRepository.findByWord(searchWord) .subscribeBy( onSuccess = { value = it }, onError = { // noop. } ) } } <- औಘͨ͠஋Ληοτ͢Δ ※දࣔͷؔ܎্ɺදهΛҰ෦লུ͍ͯ͠·͢
  2. MutableLiveData internal class CurryViewModel( private val checkCurryUseCase: CheckCurryUseCase ) :

    ViewModel() { val loading: MutableLiveData<Boolean> = MutableLiveData() fun check() { checkCurryUseCase.execute() .doOnSubscribe { loading.value = true } .doFinally { loading.value = false } .subscribeBy( onError = { // noop. } ) } } <-loadingͷ஋Λtrueʹ͢Δ <-loadingͷ஋Λfalseʹ͢Δ ※දࣔͷؔ܎্ɺදهΛҰ෦লུ͍ͯ͠·͢
  3. ͋ΔLiveDataͷ஋Λ΋ͱʹ ผͷLiveDataΛߋ৽͍ͨ͠ internal class CurryViewModel( curryLiveDataFactory: CurryLiveDataFactory, private val checkCurryUseCase:

    CheckCurryUseCase ) : ViewModel() { private val searchWord: MutableLiveData<String> = MutableLiveData() val curryLiveData: CurryLiveData = curryLiveDataFactory.create(searchWord.value.orEmpty()) fun search(searchWord: String) { this.searchWord.value = searchWord } } ˢTFBSDI8PSE͕ߋ৽͞ΕͨΒɺDVSSZ-JWF%BUBΛ࡞Γ௚͍ͨ͠
  4. Transformations#map internal class CurryViewModel( curryLiveDataFactory: CurryLiveDataFactory, private val checkCurryUseCase: CheckCurryUseCase

    ) : ViewModel() { private val searchWord: MutableLiveData<String> = MutableLiveData() val length: LiveData<Int> = Transformations.map(searchWord) { word -> word.length } fun search(searchWord: String) { this.searchWord.value = searchWord } } ˢ-JWF%BUBͷWBMVFͰ͋Δ*OUΛGVODUJPOͰฦ٫͍ͯ͠Δ
  5. Transformations#switchMap internal class CurryViewModel( curryLiveDataFactory: CurryLiveDataFactory, private val checkCurryUseCase: CheckCurryUseCase

    ) : ViewModel() { private val searchWord: MutableLiveData<String> = MutableLiveData() val curryLiveData: LiveData<List<Curry>> = Transformations.switchMap(searchWord) { word -> curryLiveDataFactory.create(word) } fun search(searchWord: String) { this.searchWord.value = searchWord } } ˢ-JWF%BUBͦͷ΋ͷΛGVODUJPOͰฦ٫͍ͯ͠Δ
  6. internal class CurryViewModel( curryLiveDataFactory: CurryLiveDataFactory, private val checkCurryUseCase: CheckCurryUseCase )

    : ViewModel() { private val searchWord: MutableLiveData<String> = MutableLiveData() val mutableCurryLiveData: MutableLiveData<List<Curry>> = MutableLiveData() val searchCurryLiveData: LiveData<List<Curry>> = Transformations.switchMap(searchWord) { word -> curryLiveDataFactory.create(word) } fun check(id: Long) { checkCurryUseCase.execute() .doOnSubscribe { val snapshot = searchCurryLiveData.value!! changeCheckState( snapshot, snapshot.find { it.id == id }!!, true ) } .subscribeBy(onError = {}) } private fun changeCheckState(snapshot: List<Curry>, target: Curry, isCheck: Boolean) { val newCurry = target.copy( check = isCheck ) mutableCurryLiveData.value = snapshot.toMutableList().apply { set(snapshot.indexOf(target), newCurry) } } } ※දࣔͷؔ܎্ɺදهΛҰ෦লུ͍ͯ͠·͢ ↑searchCurryLiveData΋࢖͍͍ͨ ↓mutableCurryData΋࢖͍͍ͨ
  7. internal class CurryViewModel( curryLiveDataFactory: CurryLiveDataFactory, private val checkCurryUseCase: CheckCurryUseCase )

    : ViewModel() { private val searchWord: MutableLiveData<String> = MutableLiveData() private val mutableCurryLiveData: MutableLiveData<List<Curry>> = MutableLiveData() private val searchCurryLiveData: LiveData<List<Curry>> = Transformations.switchMap(searchWord) { word -> curryLiveDataFactory.create(word) } val curryLiveData: LiveData<List<Curry>> = MediatorLiveData<List<Curry>>().apply { addSource(mutableCurryLiveData) { value = it } addSource(searchCurryLiveData) { value = it } } fun check(id: Long) { checkCurryUseCase.execute() .doOnSubscribe { val snapshot = searchCurryLiveData.value!! changeCheckState( snapshot, snapshot.find { it.id == id }!!, true ) } .subscribeBy(onError = {}) } private fun changeCheckState(snapshot: List<Curry>, target: Curry, isCheck: Boolean) { val newCurry = target.copy( check = isCheck ) mutableCurryLiveData.value = snapshot.toMutableList().apply { set(snapshot.indexOf(target), newCurry) } } } ※දࣔͷؔ܎্ɺදهΛҰ෦লུ͍ͯ͠·͢ ↑ LiveDataΛ௥Ճ͍ͯ͘͠
  8. Transformations @MainThread public static <X, Y> LiveData<Y> map( @NonNull LiveData<X>

    source, @NonNull final Function<X, Y> mapFunction) { final MediatorLiveData<Y> result = new MediatorLiveData<>(); result.addSource(source, new Observer<X>() { @Override public void onChanged(@Nullable X x) { result.setValue(mapFunction.apply(x)); } }); return result; }
  9. Transformations @MainThread public static <X, Y> LiveData<Y> switchMap( @NonNull LiveData<X>

    source, @NonNull final Function<X, LiveData<Y>> switchMapFunction) { final MediatorLiveData<Y> result = new MediatorLiveData<>(); result.addSource(source, new Observer<X>() { LiveData<Y> mSource; @Override public void onChanged(@Nullable X x) { LiveData<Y> newLiveData = switchMapFunction.apply(x); if (mSource == newLiveData) { return; } if (mSource != null) { result.removeSource(mSource); } mSource = newLiveData; if (mSource != null) { result.addSource(mSource, new Observer<Y>() { @Override public void onChanged(@Nullable Y y) { result.setValue(y); } }); } } }); return result; }
  10. MediatorLiveData public class MediatorLiveData<T> extends MutableLiveData<T> { private SafeIterableMap<LiveData<?>, Source<?>>

    mSources = new SafeIterableMap<>(); @MainThread public <S> void addSource(@NonNull LiveData<S> source, @NonNull Observer<? super S> onChanged) { Source<S> e = new Source<>(source, onChanged); Source<?> existing = mSources.putIfAbsent(source, e); if (existing != null && existing.mObserver != onChanged) { throw new IllegalArgumentException( "This source was already added with the different observer"); } if (existing != null) { return; } if (hasActiveObservers()) { e.plug(); } } : }
  11. MediatorLiveData private static class Source<V> implements Observer<V> { final LiveData<V>

    mLiveData; final Observer<? super V> mObserver; int mVersion = START_VERSION; Source(LiveData<V> liveData, final Observer<? super V> observer) { mLiveData = liveData; mObserver = observer; } void plug() { mLiveData.observeForever(this); } void unplug() { mLiveData.removeObserver(this); } @Override public void onChanged(@Nullable V v) { if (mVersion != mLiveData.getVersion()) { mVersion = mLiveData.getVersion(); mObserver.onChanged(v); } } }