coroutine の使い方 - Android Architecture Blueprints v2 #1

気がついたら「v2」です。MVVM のみとなって、 RxJava は姿を消していますが。

👉 googlesamples/android-architecture: A collection of samples to discuss and showcase different architectural tools and patterns for Android apps. 



現在、4つのバリエーションが公開されていますが、以下は共通。


- kotlin
- coroutine
- single activity
- architecture component
- navigation component + fragment
- presentetion layer(per page) = fragment + view model
- reactive ui = live data + data binding
- data layer = repositpory + local(room) + remote
- datalayer one shot operations(no listener or data streams)

非同期処理には、どのバリエーションも「coroutine」使う。

どのように coroutine を使っているか、を定型化しておきたい。

関数 coroutineScope

「kotlinx-coroutines-core」の関数の「coroutineScope」 が目についたので見ておく。


suspend fun <R> coroutineScope(
    block: suspend CoroutineScope.() → R
): R (source)

CoroutineScope を作成し、このスコープで指定された suspend ブロックを呼び出します。その外側のスコープから coroutineContext を継承しますが、そのコンテキストのJobをオーバーライドします。

この関数は、処理の並列分解用に設計されています。 このスコープ内のいずれかの子コルーチンが失敗すると、このスコープは失敗し、残りのすべての子はキャンセルされます(supervisorScope との違いを参照してください)。 与えられたブロックとそのすべての子コルーチンが完了するとすぐに戻ります。
スコープの使用例は次のようになります。


suspend fun showSomeData() = coroutineScope {

  val data = async(Dispatchers.IO) { // <- extension on current scope
     // ... load some UI data for the Main thread ...
  }

  withContext(Dispatchers.Main) {
    doSomeWork()
    val result = data.await()
    display(result)
  }
}

この例のスコープの意味は次のとおりです。

1. showSomeDataは、データがロードされてUIに表示されるとすぐに戻ります。
2. doSomeWorkが例外をスローすると、非同期タスクはキャンセルされ、showSomeDataはその例外を再スローします。
3. showSomeData の外部スコープが取り消されると、開始された async ブロックとwithContext ブロックの両方が取り消されます。
4. 非同期ブロックが失敗すると、withContext はキャンセルされます。

現在のジョブが外部でキャンセルされた場合、メソッドは CancellationException をスローします。このスコープ内に未処理の例外がある場合(たとえば、このスコープ内の起動で開始されたクラッシュコルーチンから)は、対応する未処理のThrowableをスローします。

coroutineScope - kotlinx-coroutines-core

実際の記述

coroutine を使った非同期処理は 各 ViewModel を起点に記述されています。


class TasksViewModel(
    private val tasksRepository: TasksRepository
) : ViewModel() {

    fun loadTasks(forceUpdate: Boolean) {
        viewModelScope.launch {

            // 対応する Repository メソッドをコール
            // val tasksResult = tasksRepository.getTasks(forceUpdate)

        }
    }

}

👉 android-architecture/TasksViewModel.kt at master · googlesamples/android-architecture 

Repository を展開して、スコープ周りを抜き出してみると、


class TasksViewModel(
    private val tasksRepository: TasksRepository
) : ViewModel() {

    fun loadTasks(forceUpdate: Boolean) {
        viewModelScope.launch {

            withContext(ioDispatcher) {
            
                // ...            

            }

        }
    }

}

というこれまで通り withContext() を使った dispatcher の切り換え。

他には、

前述の coroutineScope 関数を使った記述が、単独、並列、入れ子の3種類。


override suspend fun saveTask(task: Task) {
    coroutineScope {
        launch { tasksRemoteDataSource.saveTask(it) }
        launch { tasksLocalDataSource.saveTask(it) }
    }
}


override suspend fun clearCompletedTasks() {
    coroutineScope {
        launch { tasksRemoteDataSource.clearCompletedTasks() }
        launch { tasksLocalDataSource.clearCompletedTasks() }
    }
    withContext(ioDispatcher) {
        cachedTasks?.entries?.removeAll { it.value.isCompleted }
    }
}


override suspend fun deleteAllTasks() {
    withContext(ioDispatcher) {
        coroutineScope {
            launch { tasksRemoteDataSource.deleteAllTasks() }
            launch { tasksLocalDataSource.deleteAllTasks() }
        }
    }
}

👉 android-architecture/DefaultTasksRepository.kt at master · googlesamples/android-architecture 

今後、さらに簡潔に記述されていくのだろうが、意図は今のが理解しやすいと思いメモ。




Android Q で 画面録画機能は利用できるのか。Can we use Screen Recording on Android Q stable release?

beta1 のころは設定画面から「設定を有効化」することで可能でしたが、Screen Recording。

👉 【Android Q】 端末画面動画 (screenrecord) が簡単に録画録音できるのよ、アプリ不要! 

beta5 となった今では、設定画面から有効化する項目一覧が表示されません。

adb コマンドにて有効化します。


~ $ adb shell settings put global settings_screenrecord_long_press true
~ $ adb shell settings get global settings_screenrecord_long_press
true

録画スタートから順調に進んでいきますが、録画停止したあとに、

うまく保存できないようです。



Android Q 安定版リリース時には、利用できるようになってくれたらいいな。

👉 Android Q beta gets a screen recorder, how to access it - 9to5Google 
👉 サポートが切れた Pixel に Android 10 相当の Lineage OS 17 を 
👉 Android標準リカバリ「Android Recovery」を使う方法 


Android-Q beta5 ジェスチャーナビゲーション【動画有り】

賛否両論あるようですが。



薄いボタンが一つとなります。

Android OSでは画面下部にあるナビゲーションバーが担当している操作は以下の5つ。

1. アプリドローワーを引き出す
2. ホームの表示
3. アプリ切り換え
4. アシスタント起動
5. 戻る

これら5つの操作を1つの薄いボタンでどう操作するのでしょうか。

1. アプリドローワーを開く

ボタンを上へ長くスワイプ。

これまでと同じです。
直感的に使えます。

2. ホームの表示

ボタンを上へ長くスワイプ。

「1. アプリドローワーを開く」時の操作と同じですが、ホーム画面以外から使うことで区別できます。

3. アプリ切り換え

ボタンを上へ短くスワイプ。

アプリ切り換え画面が表示されます。

または、
ボタンを左右にスワイプで直接切り換えることもできます。

4. アシスタント起動

画面左右下隅を中央に向けてスワイプします。

5. 戻る

画面左右端を中央に向けてスワイプします。

スワイプ前に、一度ホールドすると、アプリ内のナビゲーションメニューとの操作の衝突は避けれる。

まとめ?

まだ、慣れていないためか、イライラ→絶叫してしまいます(泣)


この操作の1ボタンのジェスチャーナビゲーションを、デフォルト設定として、Qは正式リリースとなるか?

ならないよなあ。