当前位置:网站首页>Workmanager learning 1

Workmanager learning 1

2022-07-05 10:16:00 Mr_ Tony

One 、 Preface

At present, when performing long-term background tasks , Official recommendation WorkManager To handle background tasks , Here to WorkManager Make a simple record .WorkManager It can mainly perform the following tasks
 Insert picture description here

Two 、 Add dependency

dependencies {
    
    val work_version = "2.7.1"

    // (Java only)
    implementation("androidx.work:work-runtime:$work_version")

    // Kotlin + coroutines
    implementation("androidx.work:work-runtime-ktx:$work_version")

    // optional - RxJava2 support
    implementation("androidx.work:work-rxjava2:$work_version")

    // optional - GCMNetworkManager support
    implementation("androidx.work:work-gcm:$work_version")

    // optional - Test helpers
    androidTestImplementation("androidx.work:work-testing:$work_version")

    // optional - Multiprocess support
    implementation "androidx.work:work-multiprocess:$work_version"
}

3、 ... and 、 A simple example

One WorkManager It needs three parts . Define a Work, Create a WorkRequest, Submit to WorkManager To perform . Here is an example of a simple one-time task .

WorkTest.kt

class WorkTest(val appContext: Context, workerParams: WorkerParameters): Worker(appContext, workerParams) {
    
    override fun doWork(): Result {
    
        Log.e("YM--->"," Background task execution in progress , Task thread :${
      Thread.currentThread().id}--> Thread name :${
      Thread.currentThread().name}")
        return Result.success()
    }
}

Here are two kinds of creation WorkRequest The way , A complex kind of , A simple , Choose an implementation according to the situation .

    private fun initWork() {
    
// val uploadWorkRequest: WorkRequest = // Complex builder approach 
// OneTimeWorkRequestBuilder<WorkTest>()
// .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)// Set urgent tasks 
// .build()
        val uploadWorkRequest: WorkRequest = OneTimeWorkRequest.from(WorkTest::class.java)// Simple way 
        WorkManager
            .getInstance(this)
            .enqueue(periodicWorkRequest)
    }

Use WorkManager To perform

WorkManager
            .getInstance(this)
            .enqueue(periodicWorkRequest) 

Four 、 Regular tasks

A regular task can execute a task many times . The following is how to create

val saveRequest =
       PeriodicWorkRequestBuilder<WorkTest>(1, TimeUnit.HOURS)
    // Additional configuration
           .build()

Need to pay attention to the time , If the time is less than 15 minute , It will be calculated according to 15 minutes , If it is more than 15 minutes, it will be calculated according to the actual time .

Suppose you want to define a flexible time period , For example, the last 15 minutes to perform the task , You can use the following


val myUploadWork = PeriodicWorkRequestBuilder<SaveImageToFileWorker>(
       1, TimeUnit.HOURS, // repeatInterval (the period cycle)
       15, TimeUnit.MINUTES) // flexInterval
    .build()

Creating PeriodicWorkRequest Time transfer flexInterval as well as repeatInterval. Flexible time period from repeatInterval - flexInterval Start , Until the end of the interval .

The recurrence interval must be greater than or equal to PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS, The flexible interval must be greater than or equal to PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS.

5、 ... and 、 Work constraints

Here refer to the official website :

constraint This ensures that work is delayed until the best conditions are met . The following constraints apply to WorkManager.

NetworkType Constrains the amount of time required to run the work Network type . for example Wi-Fi ([UNMETERED](https://developer.android.google.cn/reference/androidx/work/NetworkType?hl=zh-cn#UNMETERED)).
BatteryNotLow If set to true, So when the device is in “ Low power mode ” when , Work doesn't work .
RequiresCharging If set to true, So the work can only run when the device is charging .
DeviceIdle If set to true, The user's equipment must be idle , To run the work . When running batch operations , This constraint can be very useful ; If you don't use this constraint , Batch operations may degrade the performance of other applications that are actively running on the user's device .
StorageNotLow If set to true, So when the storage space on the user's device is insufficient , Work doesn't work .

To create a set of constraints and associate them with a work , Please use one Contraints.Builder() establish Constraints example , And assign the instance to WorkRequest.Builder().

for example , The following code builds a work request , This work request is only available when the user's device is charging and connected to Wi-Fi It only runs when the network is running :

val constraints = Constraints.Builder()
   .setRequiredNetworkType(NetworkType.UNMETERED)
   .setRequiresCharging(true)
   .build()

val myWorkRequest: WorkRequest =
   OneTimeWorkRequestBuilder<MyWork>()
       .setConstraints(constraints)
       .build()

If more than one constraint is specified , Work will only run if all constraints are met .

If a constraint is no longer satisfied while the work is running ,WorkManager Will stop the actuator . The system will retry the work after all constraints are met .

6、 ... and 、 Delay work

The above tasks will be executed immediately by default , If you want to delay the execution, you can take the following measures :


val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
   .setInitialDelay(10, TimeUnit.MINUTES)
   .build()

It should be noted that scheduled tasks , Only the first time will be delayed .

7、 ... and 、 Retry and retry policy

If the task fails , Want to retry , You can use this method . Retry has two parameters : Retry time and retry policy . Retry time refers to the waiting time before each retry , The shortest 10s perhaps MIN_BACKOFF_MILLIS. The retry strategy refers to how the subsequent retry time increases , There are two parameters , One is linear growth LINEAR, One is exponential growth EXPONENTIAL. You cannot set a fixed time each time . If you use retry , Need to define Worker When to return Result.retry(), Can't return Result.success(). Here is the reference code :

val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
   .setBackoffCriteria(
       BackoffPolicy.LINEAR,
       OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
       TimeUnit.MILLISECONDS)
   .build()

8、 ... and 、 Job identification

Please refer to the official website :

One can be set for each work request Unique identifier , This identifier can be used to identify the job later , In order to Cancel Work or Observe its progress .

If there's a set of logically relevant work , Tagging these work items can also be helpful . By marking , You work together on a set of work requests .

for example ,WorkManager.cancelAllWorkByTag(String) All work requests with a specific tag will be cancelled ,WorkManager.getWorkInfosByTag(String) Will return a WorkInfo The object list , This list can be used to determine the current working state .

The following code shows how to add “cleanup” Mark :

val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
   .addTag("cleanup")
   .build()

Last , You can add multiple tags to a single work request . These tags are stored internally as a set of strings . You can use WorkInfo.getTags() To obtain and WorkRequest Associated tag set .

from Worker Class , You can ListenableWorker.getTags() Retrieve its tag set .

Nine 、 Pass parameters

Some jobs need to pass some parameters . You can use the following methods , The sample code is as follows :


// Define the Worker requiring input
class UploadWork(appContext: Context, workerParams: WorkerParameters)
   : Worker(appContext, workerParams) {
    

   override fun doWork(): Result {
    
       val imageUriInput =
           inputData.getString("IMAGE_URI") ?: return Result.failure()

       uploadFile(imageUriInput)
       return Result.success()
   }
   ...
}

// Create a WorkRequest for your Worker and sending it input
val myUploadWork = OneTimeWorkRequestBuilder<UploadWork>()
   .setInputData(workDataOf(
       "IMAGE_URI" to "http://..."
   ))
   .build()

Ten 、 Urgent task

According to the official website, urgent tasks are those that need to be executed immediately , For example, add a subscription , Pay bills , Send a message . But initial contact , There is no difference from other tasks . May be in WorkManager There are many tasks , It will cause tasks to queue , Urgent tasks can be inserted in front of the team to speed up the implementation .

The urgent task is to WorkManager2.7 Added when . And maybe in Android12 The foreground service runs on previous versions . Therefore, its use scenarios are limited to a certain extent .

Here are the references

stay Android 12 Before , In the working device getForegroundInfoAsync() and getForegroundInfo() Method can make WorkManager Before you call setExpedited() Display notification when .

If you want to request a task to run as an urgent job , Then all of them ListenableWorker All must be realized getForegroundInfo Method .

Be careful : If the corresponding getForegroundInfo Method , Then call on the old platform setExpedited when , May cause runtime crash .

With Android 12 Or higher version as the target platform , The front desk service can still pass the corresponding setForeground Methods use .

Be careful setForeground() May be in Android 12 Throw a runtime exception on , And in Startup is restricted An exception may be thrown .

Working device

The working device does not know whether the work it performs has been expedited . however , In some versions of Android On , If WorkRequest Be expedited , The worker can display notifications .

So ,WorkManager Provides getForegroundInfoAsync() Method , You must implement this method , Give Way WorkManager Display notifications when necessary , To start ForegroundService.

CoroutineWorker

If you use CoroutineWorker, You have to achieve getForegroundInfo(). then , stay doWork() Pass it to setForeground(). Doing so will result in Android 12 Create notifications in previous versions .

Please refer to the following example :

  class ExpeditedWorker(appContext: Context, workerParams: WorkerParameters):   CoroutineWorker(appContext, workerParams) {   override suspend fun getForegroundInfo(): ForegroundInfo {       return ForegroundInfo(           NOTIFICATION_ID, createNotification()       )   }   override suspend fun doWork(): Result {       TODO()   }    private fun createNotification() : Notification {       TODO()    }}

Be careful : You should setForeground() Packaged in try/catch In block , To capture possible IllegalStateException. If your application cannot run in the foreground at this time , Such exceptions may occur . stay Android 12 And later , You can use more detailed ForegroundServiceStartNotAllowedException.

Quota policy

You can control what happens when the application reaches its execution quota . To continue , You can deliver setExpedited()

  • OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST, This causes the job to run as a normal work request . The above code snippet demonstrates this operation .
  • OutOfQuotaPolicy.DROP_WORK_REQUEST, This will cause the request to be cancelled when the quota is insufficient .

The sample application

To see about WorkManager 2.7.0 A complete example of how to use urgent work , Please check out GitHub Upper WorkManagerSample.

Delay urgent work

The system will try to call the specified urgent job , Execute the job as soon as possible . however , Like other types of jobs , The system may delay starting new expediting work , In the following cases :

  • load : The system load is too high , When there are too many jobs already running or when the system is out of memory , That's what happens .
  • The quota : The expediting quota limit has been exceeded . The urgent work uses the quota system based on the application standby storage partition , And limit the maximum execution time in the scrolling time window . Quotas for expedited work are more restrictive than those for other types of background jobs .

It should be noted that , Inherited above Work class , yes ListenableWorker Subclasses of , So still rewrite getForegroundInfoAsync() function .

11、 ... and 、 Reference link

  1. WorkManager Getting started  |  Android developer  |  Android Developers

  2. Application Architecture : The data layer - Use WorkManager Scheduling tasks - Android developer  |  Android Developers

原网站

版权声明
本文为[Mr_ Tony]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/186/202207050949393689.html