WorkManagerはAndroidJetpack拡張ライブラリであり、延期や非同期が可能であるが、確実に実行する必要があるタスクを簡単に計画できます。ほとんどのバックグラウンドタスクでは、現在、WorkManagerの使用がAndroidプラットフォームのベストプラクティスです。
WorkManager
https://developer.android.google.cn/topic/libraries/architecture/workmanager/
Android Jetpack
https://developer.android.google.cn/jetpack/
これまで、WorkManagerシリーズについて説明してきました。
この記事では、以下について説明します。
KotlinでWorkManagerを使用する方法
CoroutineWorkerクラス
TestListenableWorkerBuilderを使用してCoroutineWorkerクラスをテストする方法
CoroutineWorker
https://developer.android.google.cn/reference/kotlin/androidx/work/CoroutineWorker
TestListenableWorkerBuilder
https://developer.android.google.cn/reference/androidx/work/testing/TestListenableWorkerBuilder
WorkManagerのKotlinバージョン
この記事のサンプルコードはKotlinで記述されており、KTXライブラリ(Kotlin Extensions)を使用しています。WorkManagerのKTXバージョンは、より簡潔で慣用的なKotlin拡張機能を提供します。WorkManagerリリースログに記載されているように、KTXバージョンのWorkManagerを使用するには、androidx.work:work-runtime-ktx依存関係をbuild.gradleファイルに追加するだけで済みます。このコンポーネントには、CoroutineWorkerおよびその他の便利なWorkManager拡張メソッドが含まれています。
KTXライブラリ
https://developer.android.google.cn/kotlin/ktx
投稿ログ
https://developer.android.google.cn/jetpack/androidx/releases/work
より簡潔で慣用的な
データオブジェクトを作成する必要があり、それをワーカークラスに渡したり、ワーカークラスから返したりする必要がある場合、KTXバージョンのWorkManagerは一種の構文上の砂糖を提供します。この場合、Java構文で実装されるコードは次のとおりです。
Data myData = new Data.Builder()
.putInt(KEY_ONE_INT, aInt)
.putIntArray(KEY_ONE_INT_ARRAY, aIntArray)
.putString(KEY_ONE_STRING, aString)
.build();
Kotlinでは、workDataOfヘルパー関数を使用してコードをより簡潔に記述できます。
inline fun workDataOf(vararg pairs: Pair<String, Any?>): Data
workDataOf
https://developer.android.google.cn/reference/kotlin/androidx/work/package-summary#workdataof
したがって、前のJava式は次のように書き直すことができます。
val data = workDataOf(
KEY_MY_INT to myIntVar,
KEY_MY_INT_ARRAY to myIntArray,
KEY_MY_STRING to myString
)
CoroutineWorker
Javaで実装できるWorkerクラス(Worker、ListenableWorker、およびRxWorker)に加えて、Kotlincoroutinesを使用して実装できる唯一のWorkクラスであるCoroutineWorkerがあります。
ワーカー
https://developer.android.google.cn/reference/androidx/work/Worker.html
ListenableWorker
https://developer.android.google.cn/reference/androidx/work/ListenableWorker
RxWorker
https://developer.android.google.cn/reference/androidx/work/RxWorker.html
コトリンの儀式
https://kotlinlang.org/docs/reference/coroutines-overview.html
CoroutineWorker
https://developer.android.google.cn/reference/kotlin/androidx/work/CoroutineWorker.html
WorkerクラスとCoroutineWorkerクラスの主な違いは次のとおりです。CoroutineWorkerクラスのdoWork()メソッドは非同期タスクを実行できるサスペンド関数ですが、WorkerクラスのdoWork()メソッドは同期タスクのみを実行できます。CoroutineWorkerのもう1つの機能は、タスクの一時停止とキャンセルを自動的に処理できることです。Workerクラスは、これらの状況を処理するためにonStopped()メソッドを実装する必要があります。
完全なコンテキスト情報については、WorkManagerでのスレッド化に関する公式ドキュメントを参照してください。ここでは、CoroutineWorkerとは何かに焦点を当て、いくつかの小さいながらも重要な違いと、WorkManagerv2.1で導入された新しいテスト機能を使用してCoroutineWorkerクラスをテストする方法について詳しく説明します。
WorkManagerでのスレッド処理
https://developer.android.google.cn/topic/libraries/architecture/workmanager/advanced/threading
前に書いたように、CoroutineWorker#doWork()は単なるサスペンド関数です。デフォルトでは、Dispatchers.Defaultで開始されます。
class MyWork(context: Context, params: WorkerParameters) :
CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
return try {
// 做点什么
Result.success()
} catch (error: Throwable) {
Result.failure()
}
}
}
CoroutineWorker#doWork()
https://developer.android.google.cn/reference/kotlin/androidx/work/CoroutineWorker.html#dowork
これは、WorkerまたはListenableWorkerの代わりにCoroutineWorkerを使用する場合の根本的な違いであることを覚えておく必要があります。
Workerとは異なり、このコードはWorkManagerの構成で指定されたExecutorでは実行されません。
先ほど述べたように、CoroutineWorker#doWork()はデフォルトでDispatchers.Defaultで開始されます。withContext()を使用して、この構成をカスタマイズできます。
class MyWork(context: Context, params: WorkerParameters) :
CoroutineWorker(context, params) {
override suspend fun doWork(): Result = withContext(Dispatchers.IO) {
return try {
// 做点什么
Result.success()
} catch (error: Throwable) {
Result.failure()
}
}
}
Dispatchers.Defaultはほとんどの状況のニーズを満たすことができるため、CoroutineWorkerが使用するDispatcherを変更する必要はほとんどありません。
KotlinでWorkManagerを使用する方法については、このコードラボを試すことができます。
codelab
https://codelabs.developers.google.com/codelabs/android-workmanager-kt/
ワーカークラスをテストする
WorkManagerには、作業を簡単にテストできる追加のツールクラスがいくつかあります。これについて詳しくは、WorkManagerテストドキュメントページおよびWorkManager2.1.0でテストするための新しいガイドをご覧ください。テストツールの元の実装では、WorkManagerをカスタマイズして同期実行として表示できるようにし、WorkManagerTestInitHelper#getTestDriver()を使用して遅延をシミュレートし、定期的なタスクをテストできます。
WorkManagerテストドキュメントページ
https://developer.android.google.cn/topic/libraries/architecture/workmanager/how-to/testing
テストにはWorkManager2.1.0を使用します
https://developer.android.google.cn/topic/libraries/architecture/workmanager/how-to/testing-210
WorkManagerTestInitHelper#getTestDriver()
https://developer.android.google.cn/reference/kotlin/androidx/work/testing/WorkManagerTestInitHelper#gettestdriver
WorkManager v2.1に新しいツールクラスTestListenableWorkerBuilderが追加されました。これにより、Workerクラスをテストする新しい方法が導入されます。
これは、CoroutineWorkerクラスにとって非常に重要な更新です。これは、TestListenableWorkerBuilderを介してWorkerクラスを直接実行して、ロジックが正しいかどうかをテストできるためです。
@RunWith(JUnit4::class)
class MyWorkTest {
private lateinit var context: Context
@Before
fun setup() {
context = ApplicationProvider.getApplicationContext()
}
@Test
fun testMyWork() {
// 获取 ListenableWorker 的实例
val worker =
TestListenableWorkerBuilder<MyWork>(context).build()
// 同步的运行 worker
val result = worker.startWork().get()
assertThat(result, `is`(Result.success()))
}
}
ここでのポイントは、CoroutineWorkerの実行結果を同期的に取得して、Workerクラスの論理動作が正しいかどうかを直接確認できることです。
TestListenableWorkerBuilderを使用して、入力データをワーカーに渡すか、runAttemptCountを設定します。これは、ワーカー内の再試行ロジックをテストするのに非常に役立ちます。
たとえば、サーバーにデータをアップロードする場合は、接続の問題の可能性を考慮して、再試行ロジックを追加できます。
class MyWork(context: Context, params: WorkerParameters) :
CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
val serverUrl = inputData.getString("SERVER_URL")
return try {
// 通过 URL 做点什么
Result.success()
} catch (error: TitleRefreshError) {
if (runAttemptCount <3) {
Result.retry()
} else {
Result.failure()
}
}
}
}
次に、テストでTestListenableWorkerBuilderを使用して、再試行ロジックが正しいかどうかをテストできます。
@Test
fun testMyWorkRetry() {
val data = workDataOf("SERVER_URL" to "[http://fake.url](http://fake.url)")
// 获取 ListenableWorker,并将 RunAttemptCount 设置为 2
val worker = TestListenableWorkerBuilder<MyWork>(context)
.setInputData(data)
.setRunAttemptCount(2)
.build()
// 启动同步执行的任务
val result = worker.startWork().get()
assertThat(result, `is`(Result.retry()))
}
@Test
fun testMyWorkFailure() {
val data = workDataOf("SERVER_URL" to "[http://fake.url](http://fake.url)")
// 获取 ListenableWorker,并将 RunAttemptCount 设置为 3
val worker = TestListenableWorkerBuilder<MyWork>(context)
.setInputData(data)
.setRunAttemptCount(3)
.build()
// 启动同步执行的任务
val result = worker.startWork().get()
assertThat(result, `is`(Result.failure()))
}
総括する
WorkManager v2.1のリリースとworkManagerテストの新機能により、CoroutineWorkerはそのシンプルさと使いやすさで輝いています。これで、Workerクラスを非常に簡単にテストでき、KotlinでWorkManagerを使用した全体的なエクスペリエンスも非常に優れています。
プロジェクトでworkmanager-runtime-ktxに含まれているCoroutineWorkerおよびその他の拡張機能を使用していない場合は、プロジェクトでそれらを使用することを強くお勧めします。Kotlin(これは私の日常業務になっています)を使用して開発する場合、これはWorkManagerを使用するための私の好ましい方法です。
この記事がお役に立てば幸いです。コメント領域にメッセージを残して、WorkManagerの使用に関する洞察や質問を共有してください。
WorkManager関連のリソース
開発者ガイド| WorkManagerでのスレッド化
https://developer.android.google.cn/topic/libraries/architecture/workmanager/
リファレンスガイド| androidx.work
https://developer.android.google.cn/reference/androidx/work/package-summary
Codelab | WorkManagerを使用してバックグラウンドタスクを処理する
https://codelabs.developers.google.com/codelabs/android-workmanager
WorkManagerの公開問題トラッカー
https://issuetracker.google.com/issues?q=componentid:409906
リリースログ| WorkManager
https://developer.android.google.cn/jetpack/androidx/releases/work
[Android-workmanager]スタックオーバーフローのタグ
https://stackoverflow.com/questions/tagged/android-workmanager
WorkManagerのソースコード(AOSPの一部)
https://android.googlesource.com/platform/frameworks/support/+/master/work
推奨読書
最後に画面をクリックします| 元の記事を読みます | Androidの公式中国文書を表示します-WorkManagerのスケジュールされたタスクを使用します