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 

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




本当にスマホはラジオを備えたのか?

毎日のジョギング時に1時間、radiko というアプリを使っていますが、
通信量が、1.5~1.8G/月 でした。

👉 radiko 

これは、格安SIM利用で、だいたい 1000~2000円/月 の範囲。

👉 格安SIMでradikoは聞ける?おすすめの回線プランを紹介! | ゴリラでもわかるBIGLOBEモバイル 


👉 エンタメフリー・オプション 通信制限にサヨナラ!|格安SIM/スマホのBIGLOBEモバイル 

ということで、

スマホでなく、「ポータブルラジオ」のがよくね?

ポータブルラジオ
価格: 1000~2000円
重さ: 160g
電源: 乾電池
通信: 使い放題



パナソニック ラジオ FM/AM/ワイドFM対応 シルバー RF-P155-S


パナソニック ラジオ FM/AM/ワイドFM対応 シルバー RF-P55-S


パナソニック AMラジオ シルバー R-P145-S


AM/FM/ワイドFM対応 ポケットラジオ オーム電機 RAD-P2227S-K(ブラック)


OHM AM/FM コンパクトポータブルラジオ [RAD-F1771M]

当然、非常時にもポータブルラジオは役立ちます。

👉 地下鉄で Radiko を途切れずに聴き続けるかんたんな方法 
👉 NexusOne や NexusS とか Desire とかでFMラジオをかんたんに受信できる件(Radikoではなくて) 


AbsentLiveData とは?

あちこちで見かける AbsentLiveData。

ViewModel の中で以下のように使われています。


val game: LiveData<RefreshableResource<GameEntity>> = Transformations.switchMap(_gameId) { gameId ->
    when (gameId) {
        BggContract.INVALID_ID -> AbsentLiveData.create()
        else -> gameRepository.getGame(gameId)
    }
}

調べてみると、

どうやら、null の入った LiveData のようです。


/**
 * A LiveData class that has `null` value.
 */
class AbsentLiveData<T : Any?> private constructor(): LiveData<T>() {
    init {
        // use post instead of set since this can be created on any thread
        postValue(null)
    }

    companion object {
        fun <T> create(): LiveData<T> {
            return AbsentLiveData()
        }
    }
}

👉 android-architecture-components/AbsentLiveData.kt at master · googlesamples/android-architecture-components 

うん、揃う。

これは、コピペで使っていきましょう。


簡単に Play Store の説明画像が作成できる「Android App Mockup (Beta)」

このサイト。

👉 App Mockup Builder for App Store & Play Store | AppMockUp 

ブラウザ上でPlayStoreにアップロードするための画像が簡単に作成できます。

まずテンプレートを選んで、

スクリーンショットをアップロードして、テキストやカラーなどを設定していきます。

すぐにそれらしくできちゃいます!!

便利なツールです。


今なら「Pixel3a」より「Pixel3」を買ったほうが良くね?

追記: 2019-07-12

Pixel3/XL が値下げ他特典を付けてGoogleより販売されています。

👉 Google Pixel 3 - 日本 - ナイトサイトで光を見る - Google Store 

--- 追記ここまで ---

「Pixel3 vs Pixel3a」 に関して、あちこちの比較を見ていますが。

5万円以下の最新Android OSスマホ「Google Pixel 3a」をPixel 3と比べながら使って見えてきた違いとは? - GIGAZINE

性能の面で、プロセッサーのスペック差はでかいような気がします。

基本的には、

「フツーに使うならPixel3a。ゲームとかヘビーな使い方するなら、Pixel3。」

という意見が多いように思います。

私が今、どちらかを買うとして、日本で、例えばドコモで買う場合を考えてみました。

👉 Pixel3 を買った人の正しい悔しがり方

料金

Pixel3a

月額1,296円x36回
(総額 46,656円)

2019年夏 新商品のご予約・ご購入手続きについて(更新) | お知らせ | ドコモオンラインショップ | NTTドコモ

Pixel3

月額1,134円×24回
(総額 27,216円)

Google Pixel 3 | ドコモオンラインショップ | NTTドコモ

支払総額では 19,440円の差、期間は Pixel3で2年、Pixel3aで3年です。

保証期間

最低保障期間で、7ヶ月の差です。

Pixel スマートフォンと Nexus 端末で Android アップデートが提供されるタイミング - Nexus ヘルプ

まとめ

Google直販 Pixel3の一括価格を調べてみると以下。

価格.com - Google Pixel 3 64GB SIMフリー 価格比較 

Google Pixel 3 - 日本 - ナイトサイトで光を見る - Google Store 

私なら、間違いなく「Pixel3」をドコモの機種変で購入します。

オンラインでは、今現在は、「在庫なし」で、今日(2019-05-28)入荷予定とのこと。

きっと、最寄りの店舗に在庫状況を含め、電話で確認するのが良いのではないかと思います。

👉 Pixel3 を買った人の正しい悔しがり方
👉 今後、Huawei端末ユーザ ができること