2021 Jul. 24.
参考ページ
雰囲気で利用しないためのAndroidにおけるKotlin-Coroutineメモ - Qiita
非同期処理のCoroutine(コルーチン)を始めてみよう!【Android・Kotlin】
ライブラリ導入
build.gradle(Module/App)に下記を記述するだけ
jarファイルの配置は不要
dependencies { implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.1' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.1' }
概要
メインスレッドクラスにCoroutineScopeをインプリメントする
launch{ }の中に非同期スレッド処理を記述する
launch{ }内では、withContext( ){ }でスレッドを使い分ける
withContext(Dispatchers.Main) { }:メインスレッド処理
withContext(Dispatchers.Default) { }:非同期スレッド処理
withContext(Dispatchers.IO) { }:入出力関係非同期スレッド処理
launch{ }内では、withContext( )の指定がなければ、withContext(Dispatchers.Main)と同じ
async(Dispatchers.XX){ }.await( )では、ブロック内がDispatchers.XXな非同期スレッドとなり、また、その実行終了を待ってメインスレッドに戻る
async(Dispatchers.XX){ }ではブロック最終行の結果が返り値となる。"val VAL=async(Dispatchers.XX){ }.await( )"でVALをメインスレッドに渡すことができる
非同期スレッド中でのスレッドの中断はThread.sleep( )ではなくdelay( )を使う
非同期スレッド処理を関数化する場合は関数定義を "suspend fun" とする
メインクラスに書いておくもの
class MainActivity : AppCompatActivity(), CoroutineScope { // coroutineの準備 private val job = Job() override val coroutineContext: CoroutineContext get() = Dispatchers.Main + job val defaultDispatcher: CoroutineDispatcher = Dispatchers.Default // 新しいコルーチンの作成時や withContext の呼び出し時に Dispatchers をハードコードしない // https://developer.android.com/kotlin/coroutines/coroutines-best-practices?hl=ja // 終了時のcoroutineのキャンセル設定 override fun onDestroy() { job.cancel() super.onDestroy() } }
launch{ }の書き方1
withContext(Dispatchers.Default) { } による非同期スレッド
launch { withContext(Dispatchers.Default) { // 非同期スレッド } // メインスレッド }
launch{ }の書き方2
async( ){ }.await( ) による非同期スレッド
launch { async(Dispatchers.IO) { // Dispatchers.IO、Dispatchers.Defaultを使い分ける // https://qiita.com/offwhite/items/94540e7cc3b330507c9c // 非同期スレッド }.await() withContext(Dispatchers.Main) { // メインスレッド }
launch{ }の書き方3
async( ) { } による非同期スレッド
launch { val retAsync = async(Dispatchers.IO){ // Dispatchers.IO、Dispatchers.Defaultを使い分ける // https://qiita.com/offwhite/items/94540e7cc3b330507c9c // 非同期スレッド } withContext(Dispatchers.Main) { // メインスレッド // async( )の結果を入れた変数を関数の引数にして利用する FUNCTION(retAsync.await()) }
非同期スレッド内でのHTTP通信例
MainActivity.kt
import android.os.Bundle import android.util.Log import androidx.appcompat.app.AppCompatActivity import kotlinx.coroutines.* import PACKAGE.PROJECT.databinding.ActivityMainBinding import java.io.BufferedReader import java.io.InputStream import java.io.InputStreamReader import java.net.HttpURLConnection import java.net.URL import kotlin.coroutines.CoroutineContext class MainActivity : AppCompatActivity(), CoroutineScope { val targetUrl : String = "http://www.google.co.jp" // coroutine準備 private val job = Job() override val coroutineContext: CoroutineContext get() = Dispatchers.Main + job // 終了時のcoroutineのキャンセル設定 override fun onDestroy() { job.cancel() super.onDestroy() } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) binding.btnStart.setOnClickListener { /* * launch{ }の中でメインスレッドと非同期スレッドを使い分ける * async( ){ }の中だけが非同期スレッド */ launch { withContext(Dispatchers.Main) { /* * メインスレッド1 * ここのコードは非同期スレッド実行前に実行される */ binding.txtVw1.setText("wait") delay(5000) } /* * 非同期スレッド * await()により、このブロックの実行後にその下のメインスレッド2が実行される * ブロック内最終行がasync( )の戻り値となる */ val resultSubThread = async(context = Dispatchers.IO) { val TIMEOUT_MILLIS = 0 // 0は無限 val sb = StringBuffer("") var httpConn: HttpURLConnection? = null val br: BufferedReader? = null val `is`: InputStream? = null val isr: InputStreamReader? = null val url = URL(targetUrl) httpConn = url.openConnection() as HttpURLConnection httpConn.connectTimeout = TIMEOUT_MILLIS // 接続にかかる時間 httpConn.readTimeout = TIMEOUT_MILLIS // データの読み込みにかかる時間 httpConn.requestMethod = "GET" // HTTPメソッド httpConn.useCaches = false // キャッシュ利用 httpConn.doOutput = false // リクエストのボディの送信を許可(GETのときはfalse,POSTのときはtrueにする) httpConn.doInput = false // レスポンスのボディの受信を許可 httpConn.connect() val responseCode = httpConn.responseCode Log.d("MyApp", responseCode.toString()) responseCode }.await() withContext(Dispatchers.Main) { // メインスレッド2 binding.txtVw1.setText(resultSubThread.toString()) } } } } }