内容へ移動
猫型iPS細胞研究所
ユーザ用ツール
ログイン
サイト用ツール
検索
ツール
文書の表示
以前のリビジョン
バックリンク
最近の変更
メディアマネージャー
サイトマップ
ログイン
>
最近の変更
メディアマネージャー
サイトマップ
現在位置:
INDEX
»
kotlin
»
coroutines
トレース:
kotlin:coroutines
この文書は読取専用です。文書のソースを閲覧することは可能ですが、変更はできません。もし変更したい場合は管理者に連絡してください。
====== coroutines ====== [[https://kotlinlang.org/docs/tutorials/coroutines/coroutines-basic-jvm.html|Your first coroutine with Kotlin]] [[https://github.com/pljp/kotlinx.coroutines/blob/japanese_translation/docs/basics.md|pljp/kotlinx.coroutines]] ===== coroutineの使い方 ===== <code xml build.gradle (Modlue.app)> dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) ・・・ androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.2" // step1 } </code> <code kotlin> package com.nekotype.ips.api import android.os.AsyncTask import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.util.Log import kotlinx.android.synthetic.main.activity_main.* import kotlinx.coroutines.* // step2 class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // click button.setOnClickListener { println("start: ${Thread.currentThread().name}") GlobalScope.launch{ println("coroutine: ${Thread.currentThread().name}") } println("end: ${Thread.currentThread().name}") } } } ↓ start: main end: main coroutine: DefaultDispatcher-worker-1 </code> ===== Threadとは比べ物にならないほど軽い! ===== <code kotlin> // thread version import kotlinx.coroutines.* import java.util.concurrent.atomic.AtomicLong import kotlin.concurrent.thread fun main() { val c = AtomicLong() for (i in 1..1_000_000L) // thread だと数秒まっても終了しないので諦めた thread(start = true) { c.addAndGet(i) } println(c.get()) } ↓ // coroutines version import kotlinx.coroutines.* import java.util.concurrent.atomic.AtomicLong import kotlin.concurrent.thread fun main() { runBlocking { val sum = deferred.sumBy { it.await() } println("Sum: $sum") } } val deferred = (1..1_000_000).map { n -> GlobalScope.async { n } } // Sum: 1784293664 </code> ===== launchと違いasyncは値を返す ===== <code kotlin> import kotlinx.coroutines.* import java.util.concurrent.atomic.AtomicLong import kotlin.concurrent.thread fun main() { runBlocking { val sum = deferred.sumBy { it.await() } println("Sum: $sum") } } val deferred = (1..1_000_000).map { n -> GlobalScope.async { delay(1000) n } } ↓ Sum: 1784293664 </code> ===== mainスレッド(UIスレッド)へのアクセスが簡単 ===== launchやasyncで新しいcoroutineを作成するが、Dispatchers.Mainで簡単にmainスレッドを呼び出せる。 今までのdoInBackgroundでpublishProgressを使ってonProgressUpdateを呼び出すようなことをしなくてよくなる。 <code kotlin> package com.nekotype.ips.myapplication import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.util.Log import kotlinx.android.synthetic.main.activity_main.* import kotlinx.coroutines.* import java.text.SimpleDateFormat import java.util.* class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val format = SimpleDateFormat("kk:mm:ss") Log.d("async", "${text1.text} ${format.format(Date())} : ouerLaunch1 : ${Thread.currentThread().name}\n\n") GlobalScope.launch { Log.d("async", "${text1.text} ${format.format(Date())} : inLaunch1 : ${Thread.currentThread().name}\n\n") async{ delay(3000) Log.d("async", "${text1.text} ${format.format(Date())} : async1 : ${Thread.currentThread().name}\n\n") } Log.d("async", "${text1.text} ${format.format(Date())} : inLaunch2 : ${Thread.currentThread().name}\n\n") async(Dispatchers.Main) { delay(1000) Log.d("async", "${text1.text} ${format.format(Date())} : async2 : ${Thread.currentThread().name}\n\n") } async { delay(500) Log.d("async","${text1.text} ${format.format(Date())} : async3 : ${Thread.currentThread().name}\n\n") async(Dispatchers.Main) { Log.d("async", "${text1.text} ${format.format(Date())} : inAsync3 : ${Thread.currentThread().name}\n\n") } } } Log.d("async","${text1.text} ${format.format(Date())} : ouerLaunch2 : ${Thread.currentThread().name}\n\n") } } ↓ 05:32:14 : ouerLaunch1 : main 05:32:14 : ouerLaunch2 : main 05:32:14 : inLaunch1 : DefaultDispatcher-worker-1 05:32:14 : inLaunch2 : DefaultDispatcher-worker-1 05:32:14 : async3 : DefaultDispatcher-worker-1 05:32:14 : inAsync3 : main // ⇒ worker-1 の内側からmainを呼び出している 05:32:15 : async2 : main 05:32:17 : async1 : DefaultDispatcher-worker-3 </code> <code kotlin> Log.d( "coroutine","start") GlobalScope.launch(Dispatchers.Main) { Log.d( "coroutine","coroutin") Text.text="click" // 画面のテキストを変更する } Log.d( "coroutine","end") ↓ 2020-01-14 06:24:17.847 7602-7602/com.nekotype.ips.coroutine D/coroutine: start 2020-01-14 06:24:17.847 7602-7602/com.nekotype.ips.coroutine D/coroutine: end 2020-01-14 06:24:17.849 7602-7602/com.nekotype.ips.coroutine D/coroutine: coroutin </code> ===== キャンセル ===== <code> private var myjob:Job? =null private var myjobs= mutableListOf<Job?>() ... myjob=GlobalScope.launch { progress_countdown.max=1000 ... // 画面を閉じた場合にコルーチンをキャンセル override fun onPause() { super.onPause() myjobs.map { Log.d("choice","cancel") it?.cancel() } } </code> ===== join ===== コルーチン内で他のコルーチンの終了を待機する。 <code kotlin> fun TestCoroutin(){ Log.d( "coroutine","start") GlobalScope.launch() { launch { Log.d( "coroutine","coroutin_inner") } Log.d( "coroutine","coroutin_outer") } Log.d( "coroutine","end") } ↓ 2020-01-14 06:29:12.311 7952-7952/com.nekotype.ips.coroutine D/coroutine: start 2020-01-14 06:29:12.340 7952-7952/com.nekotype.ips.coroutine D/coroutine: end 2020-01-14 06:29:12.347 7952-7998/com.nekotype.ips.coroutine D/coroutine: coroutin_outer 2020-01-14 06:29:12.348 7952-7999/com.nekotype.ips.coroutine D/coroutine: coroutin_inner </code> ↓ <code kotlin> fun TestCoroutin(){ Log.d( "coroutine","start") GlobalScope.launch() { launch { Log.d( "coroutine","coroutin_inner") }.join() // 待つ Log.d( "coroutine","coroutin_outer") } Log.d( "coroutine","end") } ↓ 2020-01-14 06:30:51.472 8058-8058/com.nekotype.ips.coroutine D/coroutine: start 2020-01-14 06:30:51.500 8058-8058/com.nekotype.ips.coroutine D/coroutine: end 2020-01-14 06:30:51.505 8058-8111/com.nekotype.ips.coroutine D/coroutine: coroutin_inner //順番が変わる 2020-01-14 06:30:51.508 8058-8110/com.nekotype.ips.coroutine D/coroutine: coroutin_outer //順番が変わる </code> ===== runBlockingとasync ===== runBlockingとasyncは戻り値をもつことができる。 asyncは非同期に処理する。asyncにはawaitでまつことができる。 ===== まとめ ===== UIにアクセスするには GlobalScope.launch(Dispatchers.Main) {... Jobを取得してキャンセルするには myjob=GlobalScope.launch { ... myjob.cancel() 戻り値を取得するには runBlocking async 待ちたいとき(同期) GlobalScope.launch() { launch { ... }.join() 待ちたいとき(非同期) GlobalScope.launch() { async { ... }.await()
kotlin/coroutines.txt
· 最終更新: 2020/01/14 07:03 by
ips
ページ用ツール
文書の表示
以前のリビジョン
バックリンク
文書の先頭へ