ユーザ用ツール

サイト用ツール


サイドバー

kotlin:coroutines

以前のリビジョンの文書です


coroutines

coroutineの使い方

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
 
}
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

Threadとは比べ物にならないほど軽い!

// 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

launchと違いasyncは値を返す

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

mainスレッド(UIスレッド)へのアクセスが簡単

launchやasyncで新しいcoroutineを作成するが、Dispatchers.Mainで簡単にmainスレッドを呼び出せる。
今までのdoInBackgroundでpublishProgressを使ってonProgressUpdateを呼び出すようなことをしなくてよくなる。

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

キャンセル

    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()
        }
    }
kotlin/coroutines.1574173333.txt.gz · 最終更新: 2019/11/19 23:22 by ips