尉氏网站建设,优化seo哪家好,网页设计与制作教程ps,wordpress 论坛模板一、介绍 通过前面两篇#xff0c;我们基本掌握了组件的workmanager的接入#xff0c;以及api的使用等。但是一个框架如果运用在复杂的项目中#xff0c;肯定需要有其他额外的支持#xff0c;介绍来我们将会介绍高级概念#xff0c;以及对前面的知识点进行回顾与拓展。
高…一、介绍 通过前面两篇我们基本掌握了组件的workmanager的接入以及api的使用等。但是一个框架如果运用在复杂的项目中肯定需要有其他额外的支持介绍来我们将会介绍高级概念以及对前面的知识点进行回顾与拓展。
高级概念
一、配置和初始化 默认情况下当您的应用启动时WorkManager 使用适合大多数应用的合理选项自动进行配置。如果您需要进一步控制 WorkManager 管理和调度工作的方式可以通过自行初始化 WorkManager 来自定义 WorkManager 配置 移除默认初始化程序 如需提供自己的配置必须先移除默认初始化程序。为此请使用合并规则 tools:noderemove 从 WorkManager 2.6 开始应用启动功能便已在 WorkManager 内部使用。如需提供自定义初始化程序您需要移除 androidx.startup 节点
如果您不在应用中使用应用启动功能则可以将其彻底移除。 !-- If you want to disable android.startup completely. --providerandroid:nameandroidx.startup.InitializationProviderandroid:authorities${applicationId}.androidx-startuptools:noderemove/provider
否则仅移除 WorkManagerInitializer 节点即可。 providerandroid:nameandroidx.startup.InitializationProviderandroid:authorities${applicationId}.androidx-startupandroid:exportedfalsetools:nodemerge!-- If you are using androidx.startup to initialize other components --meta-dataandroid:nameandroidx.work.WorkManagerInitializerandroid:valueandroidx.startuptools:noderemove //provider
如果您使用的 WorkManager 是 2.6 之前的版本请改为移除 workmanager-init providerandroid:nameandroidx.work.impl.WorkManagerInitializerandroid:authorities${applicationId}.workmanager-inittools:noderemove /
二、实现 Configuration.Provider 让项目 Application 类实现 Configuration.Provider 接口并提供您自己的 Configuration.Provider.getWorkManagerConfiguration() 实现。当您需要使用 WorkManager 时请务必调用方法 WorkManager.getInstance(Context)。WorkManager 会调用应用的自定义 getWorkManagerConfiguration() 方法来发现其 Configuration public class MyApp extends Application implements Configuration.Provider {NonNullOverridepublic Configuration getWorkManagerConfiguration() {Configuration.Builder builder new Configuration.Builder();builder.setMinimumLoggingLevel(android.util.Log.DEBUG);return builder.build();}
} 三、WorkManager 2.1.0 之前版本的自定义初始化 在您的应用启动时WorkManager 会使用自定义 ContentProvider 自行初始化。此代码位于内部类 androidx.work.impl.WorkManagerInitializer 中并使用默认 Configuration。自动使用默认初始化程序除非明确停用它。默认初始化程序适合大多数应用
自定义初始化
val myConfig Configuration.Builder().setMinimumLoggingLevel(android.util.Log.INFO).build()// initialize WorkManager
WorkManager.initialize(this, myConfig) 四、WorkManager中的线程处理 在 WorkManager 使用入门中我们提到 WorkManager 可以代表您异步执行后台工作。该基本实现可满足大多数应用的需求。关于更高级的用例例如正确处理正在停止的工作您应了解 WorkManager 中的线程处理和并发机制。
WorkManager 提供了四种不同类型的工作基元
Worker 是最简单的实现我们已在前面几节进行了介绍。WorkManager 会在后台线程中自动运行该基元您可以将它替换掉。请参阅工作器中的线程处理详细了解 Worker 实例中的线程处理。CoroutineWorker 是为 Kotlin 用户建议的实现。CoroutineWorker 实例公开了后台工作的一个挂起函数。默认情况下这些实例运行默认的 Dispatcher但您可以进行自定义。请参阅 CoroutineWorker 中的线程处理详细了解 CoroutineWorker 实例中的线程处理。RxWorker 是为 RxJava 用户建议的实现。如果您有很多现有异步代码是用 RxJava 建模的则应使用 RxWorker。与所有 RxJava 概念一样您可以自由选择所需的线程处理策略。请参阅 RxWorker 中的线程处理详细了解 RxWorker 实例中的线程处理。ListenableWorker 是 Worker、CoroutineWorker 和 RxWorker 的基类。这个类专为需要与基于回调的异步 API例如 FusedLocationProviderClient进行交互并且不使用 RxJava 的 Java 开发者而设计。请参阅 ListenableWorker 中的线程处理详细了解 ListenableWorker 实例中的线程处理。五、工作器中的线程处理 当您使用 Worker 时WorkManager 会自动在后台线程中调用 Worker.doWork()。该后台线程来自于 WorkManager 的 Configuration 中指定的 Executor。默认情况下WorkManager 会为您设置 Executor但您也可以自己进行自定义。例如您可以在应用中共享现有的后台 Executor也可以创建单线程 Executor 以确保所有后台工作都按顺序执行甚至可以指定一个自定义 Executor 在手动配置 WorkManager 时您可以按以下方式指定 Executor
fun initConfig()
{WorkManager.initialize(application,Configuration.Builder()// Uses a fixed thread pool of size 8 threads..setExecutor(Executors.newFixedThreadPool(8)).build()) }
接下来我们会执行一个64次的重复需要重写work
class MyWork(context: Context, workerParams: WorkerParameters) : Worker(context, workerParams) {var count 1;override fun doWork(): Result {
// TODO(Not yet implemented)repeat(64) {Log.e(Mywork, count)return Result.success()}return Result.success()}
}
只需要在doWork中进行repeat的即可。填入重复项。
repeat方法
kotlin.internal.InlineOnly
public inline fun repeat(times: Int, action: (Int) - Unit) {contract { callsInPlace(action) }for (index in 0 until times) {action(index)}
}
就是一个不停调用action的执行方法。
注意
第一点 Worker.doWork() 是同步调用 - 您应以阻塞方式完成整个后台工作并在方法退出时完成工作。如果您在 doWork() 中调用异步 API 并返回 Result那么回调可能无法正常运行。如果您遇到这种情况请考虑使用 ListenableWorker
第二点 如果当前正在运行的 Worker 因任何原因而停止它就会收到对 Worker.onStopped() 的调用。在必要的情况下只需替换此方法或调用 Worker.isStopped()即可对代码进行检查点处理并释放资源。当上述示例中的 Worker 被停止时内容的下载可能才完成了一半但即使该工作器被停止下载也会继续。
如果想同步在执行时需要对isStop进行拦截 override fun doWork(): Result {
// TODO(Not yet implemented)repeat(64) {if (!isStopped) {Log.e(Mywork, count)}}return Result.success()} 六、CoroutineWorker 中的线程处理 WorkManager 为协程提供了一流的支持。如要开始使用请将 work-runtime-ktx 包含到您的 gradle 文件中。继承 CoroutineWorker包含 doWork() 的挂起版本 class MyCoroutineWorker(appContext: Context,params: WorkerParameters
) : CoroutineWorker(appContext, params) {override suspend fun doWork(): Result {
}
} CoroutineWorker.doWork() 是一个“挂起”函数。不同于 Worker不会在 Configuration 中指定的 Executor 中运行而是默认为 Dispatchers.Default。 您可以提供自己的 CoroutineContext 来自定义这个行为。在上面的示例中您可能希望在 Dispatchers.Main上完成此操作。
override suspend fun doWork(): Result {withContext(Dispatchers.Main){}return Result.Success.success()}
CoroutineDispatcher提供了如下 Dispatchers.Default
Dispatchers.IO
Dispatchers.Main
Dispatchers.Unconfined CoroutineWorker 通过取消协程并传播取消信号来自动处理停工情况无需执行任何特殊操作来处理停工情况。 七、在其他进程中运行 CoroutineWorker 使用 RemoteCoroutineWorkerListenableWorker 的实现将工作器绑定到特定进程。
RemoteCoroutineWorker 会使用您在构建工作请求时于输入数据中提供的两个额外参数绑定到特定进程ARGUMENT_CLASS_NAME 和 ARGUMENT_PACKAGE_NAME fun BindWorkRequest() :WorkRequest{val PACKAGE_NAME packageNameval serviceName RemoteWorkerService::class.java.nameval componentName ComponentName(PACKAGE_NAME, serviceName)val data: Data Data.Builder().putString(RemoteListenableWorker.ARGUMENT_PACKAGE_NAME, componentName.packageName).putString(RemoteListenableWorker.ARGUMENT_CLASS_NAME, componentName.className).build()return OneTimeWorkRequest.Builder(MyCoroutineWorker::class.java).setInputData(data).build()} 还需要在 AndroidManifest.xml 文件中添加服务定义 serviceandroid:nameandroidx.work.multiprocess.RemoteWorkerServiceandroid:exportedfalseandroid:process:worker1 /serviceandroid:name.RemoteWorkerService2android:exportedfalseandroid:process:worker2 / RemoteWorkerService2是一个空service需要我们自己去创建。 八、RxWorker 中的线程处理 在 WorkManager 与 RxJava 之间提供互操作性。如需开始使用这种互操作性除了在您的 gradle 文件中包含 work-runtime 之外还应包含 work-rxjava3 依赖项。而且还有一个支持 rxjava2 的 work-rxjava2 依赖项您可以根据情况使用。 需要定义自己的 RxWorker替换 RxWorker.createWork() 方法以返回 SingleResult用于表示代码执行的 Result。 class MyRxWork( appContext:Context, workerParams:WorkerParameters ) : RxWorker(appContext, workerParams) {override fun createWork(): SingleResult {return Observable.range(0,100).toList().map { Result.Success }}}
注意 RxWorker.createWork() 在主线程上调用但默认情况下会在后台线程上订阅返回值。您可以替换 RxWorker.getBackgroundScheduler() 来更改订阅线程。
当 RxWorker 为 onStopped() 时系统会处理订阅因此您无需以任何特殊方式处理停工情况。 override fun getBackgroundScheduler(): Scheduler {return super.getBackgroundScheduler()} 九、ListenableWorker 中的线程处理 在某些情况下需要提供自定义线程处理策略需要处理基于回调的异步操作。在这种情况下不能只依靠 Worker 来完成操作因为它无法以阻塞方式完成这项工作。WorkManager 通过 ListenableWorker 支持该用例。ListenableWorker 是最基本的工作器 APIWorker、CoroutineWorker 和 RxWorker 都是从这个类衍生而来的。ListenableWorker 只会发出信号以表明应该开始和停止工作而线程处理则完全交您决定。开始工作信号在主线程上调用因此请务必手动转到您选择的后台线程。 抽象方法 ListenableWorker.startWork() 会返回一个将使用操作的 Result 设置的 ListenableFuture。ListenableFuture 是一个轻量级接口它是一个 Future用于提供附加监听器和传播异常的功能。在 startWork 方法中应该返回 ListenableFuture完成操作后您需要使用操作的 Result 设置这个返回结果
如果您使用的是 Guava请使用 ListeningExecutorService。否则请将 councurrent-futures 包含到您的 gradle 文件中并使用 CallbackToFutureAdapter
使用CallBackToFutureAdapter需要引入依赖
implementation(androidx.concurrent:concurrent-futures-ktx:1.1.0)
implementation(androidx.concurrent:concurrent-futures:1.1.0)
class MyListenableWorker(context: Context,params: WorkerParameters
) : ListenableWorker(context, params) {override fun startWork(): ListenableFutureResult {return CallbackToFutureAdapter.getFuture { completer -val callback object : Callback {var successes 0override fun onFailure(call: Call, e: IOException) {completer.setException(e)}override fun onResponse(call: Call, response: Response) {successesif (successes 100) {completer.set(Result.success())}}}repeat(100) {Log(info,infosssss)}callback}}
} 如果您的工作停止会发生什么如果预计工作会停止则始终会取消 ListenableWorker 的 ListenableFuture。通过使用 CallbackToFutureAdapter,您只需添加一个取消监听器即可
completer.addCancellationListener(Runnable runable,Executor executor) 十、在其他进程中运行 ListenableWorker
和CoroutineWorker 用法一样因为CoroutineWorker 也是ListenableWorker的派生类。可参考上面资料 十一、长时间运行的 worker WorkManager 为长时间运行的 worker 提供内置支持。在这种情况下WorkManager 可以向操作系统提供一个信号指示在此项工作执行期间应尽可能让进程保持活跃状态。这些 worker 可以运行超过 10 分钟。
在后台WorkManager 会代表您管理和运行前台服务以执行 WorkRequest同时还会显示可配置的通知。 ListenableWorker 现在支持 setForegroundAsync() API而 CoroutineWorker 则支持挂起 setForeground() API。这些 API 允许开发者指定此 WorkRequest 是“重要的”从用户的角度来看或“长时间运行的”任务。 从 2.3.0-alpha03 开始WorkManager 还允许您创建 PendingIntent此 Intent 可用于取消 worker而不必使用 createCancelPendingIntent() API 注册新的 Android 组件。此方法与 setForegroundAsync() 或 setForeground() API 一起使用时特别有用可用于添加一个取消 Worker 的通知操作。
步骤
1、我们需要定义一个CoroutineWorker类
2、早doWork()方法中调用setForegroundinfo:ForegroundInfo
3、这个ForegroundInfo需要我们去构建 private fun createForegroundInfo(progress: String): ForegroundInfo {val id applicationContext.getString(R.string.notification_channel_id)val title applicationContext.getString(R.string.notification_title)val cancel applicationContext.getString(R.string.cancel_download)// This PendingIntent can be used to cancel the workerval intent WorkManager.getInstance(applicationContext).createCancelPendingIntent(getId())// Create a Notification channel if necessaryif (Build.VERSION.SDK_INT Build.VERSION_CODES.O) {createChannel()}val notification NotificationCompat.Builder(applicationContext, id).setContentTitle(title).setTicker(title).setContentText(progress).setSmallIcon(R.drawable.ic_work_notification).setOngoing(true)// Add the cancel action to the notification which can// be used to cancel the worker.addAction(android.R.drawable.ic_delete, cancel, intent).build()val notificationId Random.nextInt(1,Int.MAX_VALUE)return ForegroundInfo(notificationId, notification)}RequiresApi(Build.VERSION_CODES.O)private fun createChannel() {// Create a Notification channel} ForegroundInfo是一个持有通知对象的前景info。 十二、将前台服务类型添加到长时间运行的 worker 如果您的应用以 API 级别 29或更高版本为目标平台且包含需要位置信息访问权限的长时间运行的 worker请指明该 worker 使用 location 的前台服务类型。此外如果您的应用以 Android API 级别 30或更高版本为目标平台且包含需要访问摄像头或麦克风的长时间运行的 worker请分别声明 camera 或 microphone 前台服务类型。 如需添加这些前台服务类型在应用清单中声明前台服务类型
serviceandroid:nameandroidx.work.impl.foreground.SystemForegroundServiceandroid:foregroundServiceTypelocation|microphonetools:nodemerge / 在运行时指定前台服务类型
当您调用 setForeground() 或 setForegroundAsync() 时请指定前台服务类型 FOREGROUND_SERVICE_TYPE_LOCATION、FOREGROUND_SERVICE_TYPE_CAMERA 或 FOREGROUND_SERVICE_TYPE_MICROPHONE
创建ForegroundInfo
ForegroundInfo(NOTIFICATION_ID, notification, FOREGROUND_SERVICE_TYPE_LOCATION or
FOREGROUND_SERVICE_TYPE_MICROPHONE) 十三、总结 通过以上三篇文章已完全分析完WorkManager的工作机制以及场景的使用。我们在自己的项目中或者需求中可以运用workmanager来完成一些复杂的工作提高我们的应用交互的便捷性。