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

Observable vs. LiveData

Observable vs. LiveData

Seiya Kokushi

February 27, 2018
Tweet

More Decks by Seiya Kokushi

Other Decks in Technology

Transcript

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


    ObservableField<T>
 ObservableXxx
 ObservableListなど - bindable - android.arch.lifecycle - abstract class - MutableLiveData<T>など - lifecycle aware
  2. 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にセット
  3. <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
  4. 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(); } } }
  5. 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; } }
  6. 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
  7. 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
  8. - 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); }
  9. LiveData - Lifecycle Aware - 厳密な画面遷移には不向き 
 - LiveDataはonPauseの後に購読解除される
 -

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