KotlinでのWorkManagerの実践

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のスケジュールされたタスクを使用します  


おすすめ

転載: blog.csdn.net/jILRvRTrc/article/details/108819455