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

Observable vs. LiveData

Seiya Kokushi
February 27, 2018

Observable vs. LiveData

Seiya Kokushi

February 27, 2018
Tweet

More Decks by Seiya Kokushi

Other Decks in Technology

Transcript

  1. Observable vs. LiveData CA.apk #5 Seiya Kokushi

  2. Seiya Kokushi ronnnnn ronnnnn_jp

  3. Motivation

  4. ある日のMTGにて.. それじゃあ、ViewとViewModelは
 Observableでやりとりしましょ! さんせ〜い!! よーし、新しいアーキテクチャは
 MVVMを採用するぞ〜!

  5. な、なぜLiveDataじゃないんだ!!
 そもそも、ObservableとLiveDataの
 違いって何だ〜!!!

  6. Overview

  7. ✂ ✂ Observable LiveData - android.databinding - interface - BaseObservable


    ObservableField<T>
 ObservableXxx
 ObservableListなど - bindable - android.arch.lifecycle - abstract class - MutableLiveData<T>など - lifecycle aware
  8. Pros and cons

  9. View ViewModel Observable
 LiveData Data action fetch flowable observe update

  10. Observable class MainViewModel @Inject constructor( private val randomUseCase: RandomUseCase )

    : ViewModel() { val title: ObservableField<String> = ObservableField("") val imageUrl: ObservableField<String> = ObservableField("") …
 init { randomUseCase.observe() .subscribeOn(Schedulers.io()) .subscribe({ randomData -> title.set(randomData.data.title) imageUrl.set(randomData.data.images.downsizedMedium.url) }) .let { compositeDisposable.add(it) } fetchRandomData() } … } 監視したいオブジェクトを
 Observableで宣言 値が流れてきたら
 値をObservableにセット
  11. <layout > <data> <variable name="viewModel" type="com.ronnnnn.androidsamples.ui.MainViewModel" /> </data> <RelativeLayout >

    <Button android:onClick="@{() -> viewModel.updateRandom()}” /> <TextView android:text="@{viewModel.title}" /> <ImageView imageUrl="@{viewModel.imageUrl}" /> </RelativeLayout> </layout> 値に変更があったら
 viewのpropertyが変更される Observable
  12. Observable - DataBindingを最大限活用できる - オブジェクトに変更があった時のみ、値を通知する public class ObservableField<T> extends BaseObservable

    implements Serializable { … private T mValue; … /** * Set the stored value. */ public void set(T value) { if (value != mValue) { mValue = value; notifyChange(); } } }
  13. Observable - Lifecycle Awareじゃない 
 - メモリリーク..? 
 - 値変更のlistenerが


    WeakReferenceを継承 - 画面遷移には不向き 
 - 最新の値をキャッシュする
 ので、戻るとまた遷移する private static class WeakListener<T> extends WeakReference<ViewDataBinding> { private final ObservableReference<T> mObservable; protected final int mLocalFieldId; private T mTarget; … public boolean unregister() { boolean unregistered = false; if (mTarget != null) { mObservable.removeListener(mTarget); unregistered = true; } mTarget = null; return unregistered; } … protected ViewDataBinding getBinder() { ViewDataBinding binder = get(); if (binder == null) { unregister(); // The binder is dead } return binder; } }
  14. LiveData class MainViewModel @Inject constructor( private val randomUseCase: RandomUseCase )

    : ViewModel() { val title: MutableLiveData<String> = MutableLiveData() val imageUrl: MutableLiveData<String> = MutableLiveData() … init { randomUseCase.observe() .subscribeOn(Schedulers.io()) .subscribe({ randomData -> title.postValue(randomData.data.title) imageUrl.postValue(randomData.data.images.downsizedMedium.url) }) .let { compositeDisposable.add(it) } fetchRandomData() } … } 監視したいオブジェクトを
 LiveDataで宣言 値が流れてきたら
 値をLiveDataにpost
  15. class MainActivity : AppCompatActivity() { … override fun onCreate(savedInstanceState: Bundle?)

    { super.onCreate(savedInstanceState) component.inject(this) val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main).apply { viewModel = mainViewModel } mainViewModel.imageUrl.observe(this, Observer { it ?: return@Observer binding.gifImageView.load(it) }) mainViewModel.title.observe(this, Observer { it ?: return@Observer binding.titleTextView.text = it }) } … } 値が通知されたら
 viewのpropertyを更新する LiveData
  16. - DataBindingを最大限活用できない - オブジェクトに変更がなくても、値を通知する LiveData protected void postValue(T value) {

    boolean postTask; synchronized (mDataLock) { postTask = mPendingData == NOT_SET; mPendingData = value; } if (!postTask) { return; } ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable); } @MainThread protected void setValue(T value) { assertMainThread("setValue"); mVersion++; mData = value; dispatchingValue(null); }
  17. LiveData - Lifecycle Aware - 厳密な画面遷移には不向き 
 - LiveDataはonPauseの後に購読解除される
 -

    onSaveInstanceState後の画面遷移を再現できない googlesamples/android-architecture-components/issues/63
  18. Plus one

  19. None
  20. None
  21. None
  22. sample project ronnnnn/AndroidSamples observable livedata livedatabinding (AS 3.1 canary 6+)