良い記事がたくさんあります。
読んでみましたが、きちんと理解できてる自信がありません!
MVPの中で、どのように使われているかAndroid Architecture Blueprintsで見てみましょう。
すべての非同期処理をコルーチンで置き換えます。シンプルな非同期プログラミングとなり、直感的にコード書くことができます。
Presenter
非同期処置の記述はここが起点になります。
private fun loadTasks(forceUpdate: Boolean, showLoadingUI: Boolean) = launchSilent(uiContext) {
// ...
val result = tasksRepository.getTasks()
// ...
}
メインのデータをリポジトリから取得する部分です。
launchSilent(uiContext) {
// ...
}
と見慣れない コルーチンビルダーがありますが、元の形に戻すと、
launch(
context = UI,
start = CoroutineStart.DEFAULT,
parent = null) {
// ...
}
です。
Presenterでは、launch() でコルーチンの起点を作っています。
Viewのメソッドを利用しないメソッドでは、コルーチンコンテクストは、DefaultDispatcher となり省略することができます。
Repository
override suspend fun getTasks(): Result<List<Task>> {
// ...
val result = tasksLocalDataSource.getTasks()
// ...
}
override suspend fun getTasks(): Result<List<Task>> = withContext(appExecutors.ioContext) {
// ...
Result.Success(tasksDao.getTasks())
// ...
}
TasksLocalDataSource.kt#L34-L41
Repository -> LocalDataSource とサスベンドなfunctionが深く呼ばれていきます。
LocalDataSource では、Presenterでのlauch()時のコルーチンコンテキストから、withContext(appExecutors.ioContext) として、すべて、ioContext としての DefaultDispatcher に一時的に切り替えています。
まとめ
ざっくり、コルーチン関連の入れ子関係を書いてみると、
// presenter
launch(context = UI, parent = null) {
// repository
withContext(DefaultDispatcher) {
// fetch data from database
}
}
Presenter で launch() して、Repository末端(local/remote) で withContext() でコンテクスト切り替え。
もちろん、コルーチン内から呼ばれるのは、repository の suspend な functionず。