Takuji->find;

株式会社はてなでアプリケーションエンジニアやってます、技術的な記事を書いているつもり

Architecture Components ViewModelをAutoDisposeに対応させる。

※ これはtakuji31 Advent Calendar 2018、1日目(相当)の記事です。

adventar.org

ViewModel

ViewModelは我々Androidアプリエンジニアの生活になくてはならないコンポーネントの一つである。

AndroidのActivityのインスタンス単体のライフサイクルは特定の画面のライフサイクルより短く、画面回転やメモリー不足で簡単に消される。

だが通信などの非同期処理は画面を完全に抜け出すまでやっていてほしいし、データも保持されてほしく、そういう時にViewModelを使う。

使い方は公式ドキュメントを見てほしい。

developer.android.com

AutoDispose

AutoDisposeはUberが公開しているRxJava2のDisposableを自動的にdisposeするライブラリーである。

大半の処理は実行を指示したライフサイクルに対応するライフサイクルで処理をキャンセル(createならdestroy、resumeならpause)したいものである。

これをいい感じに自動的にやってくれるライブラリーがAutoDisposeだ。

1.0.0でandroidxにも対応していて安心。

github.com

使い方は簡単でRxJavaのObservableやSingleをsubscribeする前に

observable
  .autoDisposable(scope())
  .subscribe()

などとしてやるだけである。

これだけで現在の状態に対応したライフサイクルイベントが起きた時にdisposeされる。

ViewModelをAutoDisposeに対応させる

AutoDisposeには ScopeProvider というinterfaceがあり、これを使うと今のスコープをAutoDisposeに知らせることができる。

ScopeProvider#requestScopeCompletableSource を返せばこれが完了した時に Disposable がdisposeされる。

FragmentActivity といった LifecycleOwnerScopeProvider を継承した LifecycleScopeProvider (を実装した AndroidLifecycleScopeProvider) によってAndroidのActivityやFragmentのライフサイクルに応じたスコープを返すようになっている。

一方でViewModelはonClearedという単一のライフサイクルメソッドを持っている。

AutoDisposeで管理されるViewModel内のDisposableは全て onCleared が呼ばれた時に破棄されてほしい。

なので ScopeProvider を実装して onCleared が呼ばれた時に完了する CompletableSource を返すようにしてやればよい。

abstract class BaseViewModel : ViewModel(), ScopeProvider {
  private val onClearedSubject = CompletableSubject.create();

  override fun requestScope() : CompletableSource = onClearedSubject

  @CallSuper
  override fun onCleared() {
    onClearedSubject.onComplete()
  }
}

class HogeViewModel: BaseViewModel() {
  init {
    observable
      .autoDisposable(this)
      .subscribe()
  }
}

最後に

明日も何か書きます。