シンプルなAndroidアプリ
9338 ワード
この単純なAndroidアプリはCoroutines(起動と非同期)を作成するなどの基本的なKotlin Coroutines使用を示します.
この記事はもともと1967年に出版されましたvtsen.hashnode.dev 2022年3月26日.
私はKotlin Coroutinesの基本的な使用を理解するために、この単純なAndroidアプリを作成しました.アプリケーションは、Coroutinesのジョブを作成し、それらを同時に実行する方法を示します.おそらく、使用ケースの100 %をカバーしないでしょう、おそらく少なくとも90 %?
アプリも簡単に使用してMVVM architecture なしで
3つのボタンと2表示テキスト(左と右)このアプリではありません.
両方の左のテキストと右のテキストUIを同時に
左のテキストと右のテキストは- 1で無効な値として開始されます. 起動または非同期ボタンがクリックされると、Coroutinesは0から左のテキストUIを更新するために作成されます→ 10から9と右のテキストUI→ 19
キャンセルボタンがクリックされると、両方のテキストが更新されず、値が- 1に設定されます. キャンセルボタンがクリックされない場合、両方のテキストは最終値9および19まで更新され続ける
次の2つの方法があります.
コルーチンを作成するには、作成する必要があります
ジョブが完了するのを待ちたいなら、
私たちがそれが戻り値であるのを待ちたいCoroutineをつくるために、我々は使用します
同様
デフォルトでは、コルーチンはメイン/UIスレッドで実行されます.長い実行中のタスクを別のスレッドに移動してメイン/UIスレッドをブロックしないようにします.
異なるスレッドに切り替えるには、 あなた自身の糸を使うために、あなたは新しい糸/newをつくることができます
コルーチンを作成するとき
コルーチンのジョブをキャンセルするには
注意する1つの重要なものは、Coroutineキャンセルは協力的です.コルーチンが非協力的なキャンセルであるなら、我々はそれをキャンセルすることができません.COOTINEは完了するまで実行されます
コルーチンを解除するには、次のようにします.
たとえば、以下のような長期的なタスクを持っている場合、Coroutineは
コルーチンがキャンセルされたときは
coroutineをデバッグするには、最も簡単な方法です.
例
これまでのところ、私のすべてpersonal projects 上記のケースを使用するすべてのコルーチンを使用しないでください.私だけ使用
[更新日: 2022年4月13日]
githubリポジトリvinchamp77/Demo_CoroutinesBasics
kotlinx.coroutines.delay() vs Thread.sleep() Kotlin Tips and Tricks
この記事はもともと1967年に出版されましたvtsen.hashnode.dev 2022年3月26日.
私はKotlin Coroutinesの基本的な使用を理解するために、この単純なAndroidアプリを作成しました.アプリケーションは、Coroutinesのジョブを作成し、それらを同時に実行する方法を示します.おそらく、使用ケースの100 %をカバーしないでしょう、おそらく少なくとも90 %?
アプリも簡単に使用してMVVM architecture なしで
Model
を参照).アプリ概要
3つのボタンと2表示テキスト(左と右)このアプリではありません.
両方の左のテキストと右のテキストUIを同時に
左のテキストと右のテキストは- 1で無効な値として開始されます.
CoroutineScope.launch
CoroutineScope.async
コアスコープランチ
コルーチンを作成するには、作成する必要があります
CoroutineScope
ファースト.インViewModel
, CorotineScope
が既に生成されている(つまり、viewModelScope
). だからそれは非常に自分でそれを作成するのを使用することをお勧めします.つの利点は、すべてのCoroutineScope
子供は自動的にキャンセルされますViewModel
が破壊される.// Create new coroutine - current job is the parent job
currentJob = viewModelScope.launch {
// Create a first new sub-coroutine - job1 is the child job
val job1 = launch {
...
}
// Create a second new sub-coroutine - job2 is the child job
val job2 = launch {
...
}
// job1 and job2 are coroutines that run concurrently
// wait for both job1 and job2 to complete
job1.join()
job2.join()
...
}
CoroutineScpoe.launch
が非ブロッキング関数で、Job
すぐに.並行性を達成するために、我々は呼び出すことができますCoroutineScpoe.launch
同じコルーチンスコープ内の複数回.job1
左のテキストUIとjob2
右のテキストUIを更新する責任があります.ジョブが完了するのを待ちたいなら、
Job.join()
サスペンド機能.ジョブが次の行に移動する前にジョブが完了するまで待機します.コアスコープ非同期
私たちがそれが戻り値であるのを待ちたいCoroutineをつくるために、我々は使用します
CoroutineScope.async
. 同様
CoroutineScpoe.launch
, CoroutineScope.async
は非ブロッキング機能です.返す代わりにJob
, it returns Deferred<T>
. の最後の行async block
, 返り値T
. 例えば、getData()
リターンInt
, したがって、T
is Int
種類// Create new coroutine
viewModelScope.launch {
// Create a sub-coroutine with async
val deferred = async {
...
getData()
}
// wait for async to return it's value
data.value = deferred.await()
...
}
代わりにJob.join()
, あなたの電話Deferred<T>.awailt()
待つCoroutineScope.async
を返します.getData()
.コアスコープwithcontext ()
デフォルトでは、コルーチンはメイン/UIスレッドで実行されます.長い実行中のタスクを別のスレッドに移動してメイン/UIスレッドをブロックしないようにします.
異なるスレッドに切り替えるには、
CoroutineDispatcher
. ここで一般的な定義済みCoroutineDispatcher
を使うことができます.Dispatchers.Main
- メインスレッドDispatchers.Default
- スレッドスレッドDispatchers.IO
- ネットワークオペレーションスレッドCoroutineDispatcher
使用newSingleThreadContext("MyOwnThread")
. ほとんどの場合、定義済みのCoroutineDispatcher
十分です.コルーチンを作成するとき
launch
or async
, あなたはCoroutineDispatcher
.viewModelScope.launch {
// Create coroutine that runs on Dispatchers.Default thread
launch(Dispatchers.Default) {
loadData()
}
// Create coroutine that runs on Dispatchers.Default thread
async(Dispatchers.Default) {
loadData()
}
}
しかし、より良い解決策はCoroutineScope.withContext()
を指定するのではなく、CoroutineDispatcher
Coroutineの作成中.サスペンド機能をmain/uiスレッドから安全に呼び出すことが推奨されます.private suspend fun loadData() {
//Switches / moves the coroutine to different thread
withContext(Dispatchers.Default) {
...
}
}
Please note
CoroutineScope.withContext()
does NOT create a new coroutine. It moves the coroutines to a different thread.
ジョブ.cancel ()
コルーチンのジョブをキャンセルするには
Job.cancel()
and Job.join()
. ほとんどの時間、あなたは単に呼び出すことができますJob.cancelAndJoin()
. 注意してくださいJob.cancelAndJoin()
はサスペンド機能です.だから、コルーチンの内側にそれを呼び出す必要があります.fun onCancelButtonClick() {
if (currentJob == null) return
viewModelScope.launch() {
currentJob!!.cancelAndJoin()
}
}
currentJob
is an existing coroutine job that was created before.
コントリックス.コルーチン.yield ()
注意する1つの重要なものは、Coroutineキャンセルは協力的です.コルーチンが非協力的なキャンセルであるなら、我々はそれをキャンセルすることができません.COOTINEは完了するまで実行されます
Job.cancel()
が呼び出されました.コルーチンを解除するには、次のようにします.
CoroutineScope.isActive
kotlinx.coroutines.yield()
CoroutineScope.isActive
必要CoroutineScope
オブジェクトをコールし、コルーチンを終了するロジックを追加する必要があります.以来yield()
任意のsuspend関数で呼び出すことができます、私は個人的にそれを使用して好む.Please note the
kotlinx.coroutines.delay()
also make the coroutine cancellation cooperative.
たとえば、以下のような長期的なタスクを持っている場合、Coroutineは
Job.cancel()
リクエスト.private suspend fun simulateLongRunningTask() {
repeat(1_000_000) {
Thread.sleep(100)
}
}
それを受け入れるようにするJob.cancel()
リクエストを追加する必要がありますyield()
.private suspend fun simulateLongRunningTask() {
repeat(1_000_000) {
Thread.sleep(100)
yield()
}
}
コントリックス.コルーチン.JobCancellationException
コルーチンがキャンセルされたときは
kotlinx.coroutines.JobCancellationException
例外がスローされます.あなたは例外をキャッチし、いくつかのクリーンアップを実行することができます.currentJob = viewModelScope.launch {
try {
val job1 = launch {
...
}
val job2 = launch {
...
}
job1.join()
job2.join()
} catch (e: Exception) {
// clean up here
currentJob = null
}
}
コントリックス.コルーチン.コアテキスト
coroutineをデバッグするには、最も簡単な方法です.
kotlinx.coroutines.coroutineContext
ログ記録に非常に便利です.これは、コルーチンとスレッド情報を提供します.Please note that it is a suspend property which can only be called from the suspend function.
例
Utils.log()
ユーティリティのサスペンド機能をラップする.Log.d()
:object Utils {
suspend fun log(tag: String, msg: String) {
Log.d(tag, "$coroutineContext: $msg")
}
}
//Usage
Utils.log("ViewModel", "======= Created launch coroutine - onButtonClick() =======")
LOGCAT出力の例:D/ViewModel: [StandaloneCoroutine{Active}@5261b32, Dispatchers.Main.immediate]: ======= Created launch coroutine - onButtonClick() =======
いくつかの考え
これまでのところ、私のすべてpersonal projects 上記のケースを使用するすべてのコルーチンを使用しないでください.私だけ使用
CoroutineScope.launch
and CoroutineScope.withContext()
私が欲しいものを成し遂げるには、どれが十分です.私は、私はしたい場合は、私は私がすることができますが、まだアプリケーションが完全に動作するCoroutineをキャンセルする必要はありません.[更新日: 2022年4月13日]
joinAll()
シーケンシャルにコードを実行するのではなく、いくつかのネットワークコールを並列化します.以下の例private suspend fun fetchArticlesFeed() : List<ArticleFeed> = coroutineScope {
val results = mutableListOf<ArticleFeed>()
val jobs = mutableListOf<Job>()
for(url in urls) {
val job = launch {
val xmlString = webService.getXMlString(url)
val articleFeeds = FeedParser().parse(xmlString)
results.addAll(articleFeeds)
}
jobs.add(job)
}
jobs.joinAll()
return@coroutineScope results
}
ソースコード
githubリポジトリvinchamp77/Demo_CoroutinesBasics
参考
Reference
この問題について(シンプルなAndroidアプリ), 我々は、より多くの情報をここで見つけました https://dev.to/vtsen/kotlin-coroutines-basics-simple-android-app-demo-2p2fテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol