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

    View Slide

  2. Seiya Kokushi
    ronnnnn
    ronnnnn_jp

    View Slide

  3. Motivation

    View Slide

  4. ある日のMTGにて..
    それじゃあ、ViewとViewModelは

    Observableでやりとりしましょ!
    さんせ〜い!!
    よーし、新しいアーキテクチャは

    MVVMを採用するぞ〜!

    View Slide

  5. な、なぜLiveDataじゃないんだ!!

    そもそも、ObservableとLiveDataの

    違いって何だ〜!!!

    View Slide

  6. Overview

    View Slide



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

    ObservableField

    ObservableXxx

    ObservableListなど
    - bindable
    - android.arch.lifecycle
    - abstract class
    - MutableLiveDataなど
    - lifecycle aware

    View Slide

  8. Pros and cons

    View Slide

  9. View
    ViewModel Observable

    LiveData
    Data
    action
    fetch flowable
    observe
    update

    View Slide

  10. Observable
    class MainViewModel @Inject constructor(
    private val randomUseCase: RandomUseCase
    ) : ViewModel() {
    val title: ObservableField = ObservableField("")
    val imageUrl: ObservableField = 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にセット

    View Slide



  11. name="viewModel"
    type="com.ronnnnn.androidsamples.ui.MainViewModel" />


    android:onClick="@{() -> viewModel.updateRandom()}” />
    android:text="@{viewModel.title}" />
    imageUrl="@{viewModel.imageUrl}" />


    値に変更があったら

    viewのpropertyが変更される
    Observable

    View Slide

  12. Observable
    - DataBindingを最大限活用できる
    - オブジェクトに変更があった時のみ、値を通知する
    public class ObservableField extends BaseObservable implements Serializable {

    private T mValue;

    /**
    * Set the stored value.
    */
    public void set(T value) {
    if (value != mValue) {
    mValue = value;
    notifyChange();
    }
    }
    }

    View Slide

  13. Observable
    - Lifecycle Awareじゃない 

    - メモリリーク..? 

    - 値変更のlistenerが

    WeakReferenceを継承
    - 画面遷移には不向き 

    - 最新の値をキャッシュする

    ので、戻るとまた遷移する
    private static class WeakListener
    extends WeakReference {
    private final ObservableReference 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;
    }
    }

    View Slide

  14. LiveData
    class MainViewModel @Inject constructor(
    private val randomUseCase: RandomUseCase
    ) : ViewModel() {
    val title: MutableLiveData = MutableLiveData()
    val imageUrl: MutableLiveData = 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

    View Slide

  15. class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    component.inject(this)
    val binding = DataBindingUtil.setContentView(this, R.layout.activity_main).apply {
    viewModel = mainViewModel
    }
    mainViewModel.imageUrl.observe(this, Observer {
    it ?: [email protected]
    binding.gifImageView.load(it)
    })
    mainViewModel.title.observe(this, Observer {
    it ?: [email protected]
    binding.titleTextView.text = it
    })
    }

    }
    値が通知されたら

    viewのpropertyを更新する
    LiveData

    View Slide

  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);
    }

    View Slide

  17. LiveData
    - Lifecycle Aware
    - 厳密な画面遷移には不向き 

    - LiveDataはonPauseの後に購読解除される

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

    View Slide

  18. Plus one

    View Slide

  19. View Slide

  20. View Slide

  21. View Slide

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

    View Slide