Kotlin で 非同期処理 Coroutine #1 ~ launch(), async()

ネット上を調べてみてもよくわかりません。

難しい言葉や experimental な仕様の変更などあったりして。

少しづつ試してみながらマスターしていきましょう。

// build.gradle

implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:0.22.2"

//gradle.properties

kotlin.coroutines=enable

kotlinx.coroutines/coroutines-guide-ui.md at master · Kotlin/kotlinx.coroutines

まず、これ。


for (i in 1..10) {
  Timber.d("$i")
  Thread.sleep(1000)
}

非同期にしたいですよね。
launch から始めます。


launch { // @
  for (i in 1..10) {
    Timber.d("$i")
    Thread.sleep(1000)
  }
}


launch {
  for (i in 1..10) {
    Timber.d("$i")
    delay(1000)  // @
  }
}

引数をつけて渡す。

UI :
UIスレッドで実行。

CommonPool :
バックグランドスレッドで実行。


launch(UI) {  // @
  for (i in 1..10) {
    Timber.d("$i")
    delay(1000)
  }
}


launch(CommonPool) {  // @
  for (i in 1..10) {
    Timber.d("$i")
    delay(1000)
  }
}


launch(UI + CommonPool) {  // @
  for (i in 1..10) {
    Timber.d("$i")
    delay(1000)
  }
}

launch() の戻りからキャンセルできます。


val job = launch(UI) {  // @
  for (i in 1..10) {
    Timber.d("$i")
    delay(1000)
  }
}

fab.setOnClickListener {
  job.cancel() // @
}

 

まとめ

UIスレッドに限定されたコルーチンは、UIスレッドをブロックすることなく、UI内の何かを自由に更新して中断することができます。

delay が待っている間UIスレッドはブロックされないのでUIはフリーズしません。ただ単にコルーチンを中断します。

Job.cancelは完全にスレッドセーフでノンブロッキングです。
実際に終了するのを待つことなく、コルーチンがそのジョブをキャンセルするように通知するだけです。 どこからでも呼び出すことができます。

基本的な非同期呼び出しは、launch() と async() の2つ。似ているが戻りが異なる。


【Android Studio】メニューバーをAndroidStudioに移動する

Mac OSのメニューバーにメニューが表示されて、他アプリのアイコンが表示できなくなって困ることがあります。

Android Studio内に移動しましょう。

[Help] - [Edit Custom Properties...]


# custom Android Studio properties

# メニューを Android Studio ウィンドウに表示
apple.laf.useScreenMenuBar=false

動画内1分23秒付近で説明されています。

ファイルの実態は以下のようです。

~/Library/Preferences/AndroidStudio3.0/idea.properties


【Android Studio】ビルド環境を安定した最新バージョンにする

様々なものに依存したAndroidアプリ開発環境は最新なものにしたいものです。

「開発環境」と一言で言ったりしますが、Android Studio は様々な「バージョン」で構成されています。

今回は、Android Studio上で、その中でもいわゆる「ビルド環境」的な部分について設定してみます。

 

Android Studio Gradle Plugin

Android Studio を標準的に、当たりまえに使うにはGradleを利用するこのプラグインが必須です。

先述のGradleのバージョンはこのプラグインに強く依存しています、

Android Plugin for Gradle Release Notes | Android Studio

よって、Gradle のバージョンアップの際にはここを確認するとよいです。

パッケージ名が「com.android.tools.build:gradle」となり、現在はGoogleのリポジトリで管理されています。

Google's Maven Repository

設定変更は、Project/build.gradle です。


buildscript {

    repositories {
        google()
    }

    dependencies {  
        classpath 'com.android.tools.build:gradle:3.0.1'
    }
}

 

Gradle

Android Studioで使う際、推奨されているのは Gradle Wrapper なスタイルです。

Gradle Distributions

以下ファイルで最新版の設定をしましょう。

gradle/wrapper/gradle-wrapper-properties


distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4.1-all.zip

 

Kotlin Gradle Plugin / Kotlin

もうKotlinでいいですよね。

StackOverFlowでも時代遅れなコードばかりで段階的なバージョン各過程を含めたコードばかりでその確認に四苦八苦して時間を費やすことになりますがKotlinなキーワードで検索すればその手間を避けることができます。

最近は公式系ドキュメントでもKotlinが優先されており、Kotlin化はさらに加速していくのは間違いありません。

Saving Files | Android Developers

KotlinをGradleで利用するには、このプラグインを利用することになります。

Android Studio – Migration from Maven Central to JCenter | Blog @Bintray

java - Android buildscript repositories: jcenter VS mavencentral - Stack Overflow

最新版の確認は、jetbrainsが管理しているMVNRepositoryで確認することができます。


Maven Repository: org.jetbrains.kotlin » kotlin-gradle-plugin

設定変更は同じ、Project/build.gradle です。


buildscript {
    ext.kotlin_version = '1.2.20'

    repositories {
        jcenter()
    }

    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

 

まとめ

以上をまとめておきます。

Project/build.gradle


buildscript {

    // kotlin / kotlin gradle plugin version
    ext.kotlin_version = '1.2.20'

    repositories {
        google()
        jcenter()
    }

    dependencies {

      // android studio gradle plugin
      // https://dl.google.com/dl/android/maven2/index.html
      classpath 'com.android.tools.build:gradle:3.0.1'

      // kotlin / kotlin gradle plugin
      // https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-gradle-plugin
      classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

gradle/wrapper/gradle-wrapper-properties


distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

# https://services.gradle.org/distributions/
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4.1-all.zip

オープンソースを利用したプラットフォームや開発環境のバージョンの調整は

「stable最新」

にしておくことが幸せになることの王道です。

関連各所の利益や手間を考慮したしがらみが悩みのタネですよね。

Gradle Dependency バージョンのチェックを「最新」に更新する方法


Java から Kotlin 移行の進捗を「cloc」で確認する

これを確認したかったのです.

特定のディレクトリのファイルやコード行数の確認.

googlesamples/android-architecture at todo-mvp-rxjava

「cloc」てやつを使います.

AlDanial/cloc: cloc counts blank lines, comment lines, and physical lines of source code in many programming languages.

こんな感じで結果表示されます.


for d in ./*/ ; do (cd "$d" && echo "$d" && cloc --vcs git); done

Android プロジェクトの場合, アプリのルートディレクトリでやると,


$ pwd
/Users/maochanz/projects/PlainTemplates
$ cloc .
     674 text files.
     567 unique files.
     140 files ignored.

github.com/AlDanial/cloc v 1.74  T=10.63 s (50.4 files/s, 8239.6 lines/s)
--------------------------------------------------------------------------------
Language                      files          blank        comment           code
--------------------------------------------------------------------------------
JSON                            253              0              0          30758
XML                             223           1749            233          17707
Java                             36             38          24757          10428
Kotlin                           18            245            324            993
Bourne Again Shell                1             19             20            121
DOS Batch                         1             24              2             64
Groovy                            3              8              3             55
Prolog                            1              3              0             18
--------------------------------------------------------------------------------
SUM:                            536           2086          25339          60144
--------------------------------------------------------------------------------

となって,

build ディレクトリもカウントされるので,

src ディレクトリ以下で実行するといいでしょう.


$ pwd
/Users/maochanz/projects/PlainTemplates/app/src
$ cloc .
      77 text files.
      76 unique files.
       1 file ignored.

github.com/AlDanial/cloc v 1.74  T=0.44 s (171.9 files/s, 7442.6 lines/s)
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
XML                             58            177             89           1463
Kotlin                          18            245            324            993
-------------------------------------------------------------------------------
SUM:                            76            422            413           2456
-------------------------------------------------------------------------------

Kotlin による冗長なコードの削減具合もよく分かるはずです.

CLOC -- Count Lines of Code


【AndroidStudio 3.0】「flavor dimension」とは何?

AndroidStudio 3.0 にアップデートしましたが,

こんな build.gradle で 以下のエラーです.


android {
  // ...
}

productFlavors {
  flavor1 {
    // ...
  }
}

buildTypes {
  release {
    // ...
  }
  debug {
    // ...
  }
}


Error:All flavors must now belong to a named flavor dimension. Learn more at https://d.android.com/r/tools/flavorDimensions-missing-error-message.html

StackOverflowで調べてみると以下の記述で大丈夫と書かれている.

Android Studio 3.0 Flavor Dimension Issue - Stack Overflow


android {
  // ...

  flavorDimensions "default" // OK
  //flavorDimensions "versionCode" // OK

}

productFlavors {
  flavor1 {
    // ...
  }
}

buildTypes {
  release {
    // ...
  }
  debug {
    // ...
  }
}

これでビルドは通る.

なんだか気持ち悪いし意味が不明すぎますね.

 

試してみる

いろいろやってみましたが, 以下のような記述がOKです.


android {
  // ...

  flavorDimensions "a"
}

productFlavors {
  flavor1 {
    // ...
  }
}

buildTypes {
  release {
    // ...
  }
  debug {
    // ...
  }
}

productFlavor を複数にする.


android {
  // ...

  flavorDimensions "a"

}

productFlavors {

  flavor1 {
    // ...
  }

  flavor2 {
    // ...
  }

  flavor3 {
    // ...
  }

  flavor4 {
    // ...
  }

}

buildTypes {
  release {
    // ...
  }
  debug {
    // ...
  }
}

flavorDimensions で productFlavor を2段階に分ける.


android {
  // ...
  flavorDimensions "a", "b"
}

productFlavors {

  flavor1 {
    dimension "a"
    // ...
  }

  flavor2 {
    dimension "a"
    // ...
  }

  flavor3 {
    dimension "b"
    // ...
  }

  flavor4 {
    dimension "b"
    // ...
  }
}

buildTypes {
  release {
    // ...
  }
  debug {
    // ...
  }
}

dimension で階層化された Build Variant が作成される.

 

まとめ

もともと productFlavor では以下のようなものが設定できました.

- applicationId
- versionCode
- minSdkVersion
- versionName/Suffix
- ソースコードやリソースの位置
- dependencies

これらを階層化させたい場合に使うのがいいように思います.

まずは, 開発時の時間短縮でしょうか.


flavorDimensions "minSdkVersion", "others"

Migrate to Android Plugin for Gradle 3.0.0 | Android Studio

ビルド バリアントの設定 | Android Studio