前言
由于笔者目前水平限制,表达能力有限,尽请见谅。
WorkManager 是 Android Jetpack 库的一部分,提供了一种向后兼容的方式来安排可延迟的异步任务,这些任务即使在应用退出或设备重启后也应该继续执行,它是 Android 推荐的解决方案,用于处理需要保证执行的后台任务。WorkManager 适合用于那些不需要立即执行的任务,但最终需要完成的任务。
上文主要深入了Constraints类,接下来将继续深入。
正文
Configuration
Configuration
类被用于配置WorkManager
行为,允许自定义Configuration
,调整WorkManager
的一些关键参数,比如日志级别、线程池大小、最大运行时间等。这些配置决定了WorkManager
如何调度和执行后台任务。
平时使用的方法如下
val config = Configuration.Builder()
.setMinimumLoggingLevel(Log.DEBUG)
.setMaxSchedulerLimit(10)
.build()
WorkManager.initialize(context, config)
创建了Configuration
实例,设置最小日志级别为DEBUG
,最大调度限制设置为10。
调用WorkManager.initialize()
方法并传入这个配置实例来初始化WorkManager。
具体的,在workManager里会这么处理这个config。
与此同时,关键部分createWorkManager的代码如下
@JvmName("createWorkManager")
@JvmOverloads
fun WorkManagerImpl(
context: Context,
configuration: Configuration,
workTaskExecutor: TaskExecutor = WorkManagerTaskExecutor(configuration.taskExecutor),
workDatabase: WorkDatabase =
WorkDatabase.create(
context.applicationContext, workTaskExecutor.serialTaskExecutor,
configuration.clock,
context.resources.getBoolean(R.bool.workmanager_test_configuration)
),
trackers: Trackers = Trackers(context.applicationContext, workTaskExecutor),
processor: Processor = Processor(
context.applicationContext, configuration, workTaskExecutor, workDatabase
),
schedulersCreator: SchedulersCreator = ::createSchedulers
): WorkManagerImpl {
val schedulers = schedulersCreator(
context, configuration,
workTaskExecutor, workDatabase, trackers, processor
)
return WorkManagerImpl(
context.applicationContext, configuration, workTaskExecutor, workDatabase,
schedulers, processor, trackers
)
}
createWorkManager
很多人可能会疑惑,只看到了@JvmName("createWorkManager"),没有看到createWorkManager这个方法啊,这里就引入了kotlin的特殊用法法。
使用@JvmName
注解在Kotlin代码中,这意味着在编译成Java字节码时,方法或属性的名称将会被替换为@JvmName
注解指定的名称。
@JvmName("createWorkManager")
注解应用于WorkManagerImpl
构造函数的一种特殊使用方式上,使Java代码中调用这个Kotlin函数时,它会被当作一个名为createWorkManager
的静态方法。尽管在Kotlin源码中不存在名为createWorkManager
的显式定义方法,在编译后的Java字节码中,WorkManagerImpl
的这个构造逻辑或相似逻辑将通过一个静态方法createWorkManager
来暴露。
为什么这样用?允许Kotlin开发者在生成的Java API中自定义命名,以提供更清晰、更符合Java习惯的接口,或者解决可能的命名冲突。
他干了什么?
-
实例化
WorkManagerImpl
:使用给定的Configuration
和Context
,以及可选的TaskExecutor
(如果没有提供,则使用默认的),创建WorkManagerImpl
的实例。WorkManagerImpl
是WorkManager
抽象类的实现,负责实际的工作调度和执行逻辑。 -
构建
WorkDatabase
:这个数据库用于存储所有的工作请求信息和状态。WorkDatabase.create
方法根据提供的Configuration
和TaskExecutor
构建数据库实例。 -
创建
Trackers
和Processor
:这些组件用于跟踪工作的状态和执行工作。Trackers
负责监听系统条件的变化,Processor
则负责处理和执行工作请求。 -
调度器:根据配置和环境,选择和创建最合适的调度器(
Scheduler
)实例。调度器负责决定何时以及如何执行工作,例如,它可能决定在设备充电时执行某项工作,或者在满足特定的网络条件时执行。 -
返回
WorkManagerImpl
实例:createWorkManager
函数构建的WorkManagerImpl
实例被用作WorkManager
的全局单例。
这里要注意到一个特殊用法,
在Kotlin中,::
操作符是用来引用类的成员(方法或属性)或者类的构造函数的。当它用在函数前面时,意味着创建一个对那个函数的引用,而不是调用那个函数。这样的引用可以被存储在变量中,或者作为参数传递给其他函数。
调度器Scheduler
而createSchedulers的相关代码如下:
typealias SchedulersCreator = (
context: Context,
configuration: Configuration,
workTaskExecutor: TaskExecutor,
workDatabase: WorkDatabase,
trackers: Trackers,
processor: Processor
) -> List<Scheduler>
fun schedulers(vararg schedulers: Scheduler): SchedulersCreator =
{ _, _, _, _, _, _ -> schedulers.toList() }
private fun createSchedulers(
context: Context,
configuration: Configuration,
workTaskExecutor: TaskExecutor,
workDatabase: WorkDatabase,
trackers: Trackers,
processor: Processor,
): List<Scheduler> =
listOf(
Schedulers.createBestAvailableBackgroundScheduler(context, workDatabase, configuration),
GreedyScheduler(
context, configuration, trackers, processor,
WorkLauncherImpl(processor, workTaskExecutor),
workTaskExecutor
),
)
typealias
定义类型别名,SchedulersCreator
表示一个函数类型,这个函数接收一系列参数(Context
、Configuration
等)并返回List<Scheduler>。
createSchedulers
函数,符合SchedulersCreator
的签名,接收相同的参数并返回一个List<Scheduler>
。
::createSchedulers
用法则创建了一个对createSchedulers
函数的引用使得在上下文中可以把createSchedulers
作为参数传递给期望SchedulersCreator
类型参数的函数或者变量。
val schedulersCreator: SchedulersCreator = ::createSchedulers
对于如下部分关键代码:
List<Scheduler> =
listOf(
Schedulers.createBestAvailableBackgroundScheduler(context, workDatabase, configuration),
GreedyScheduler(
context, configuration, trackers, processor,
WorkLauncherImpl(processor, workTaskExecutor),
workTaskExecutor
),
做了以下两件事:
-
调用
尝试创建最适合当前设备条件的后台任务调度器。Schedulers.createBestAvailableBackgroundScheduler
: -
创建
GreedyScheduler
实例:GreedyScheduler
是一种贪婪的调度器,它会尽可能立即执行工作。
至于为什么要创建两个调度器,不清楚。但总之:
正常使用,通过createBestAvailableBackgroundScheduler
选择最合适的调度方式,会让任务能够在适当的时候执行,最大限度地节约设备资源。
其他的,在需要立即执行任务的场景下,通过GreedyScheduler可以
快速地执行任务。
createBestAvailableBackgroundScheduler函数如下
@NonNull
static Scheduler createBestAvailableBackgroundScheduler(@NonNull Context context,
@NonNull WorkDatabase workDatabase, Configuration configuration) {
Scheduler scheduler;
if (Build.VERSION.SDK_INT >= WorkManagerImpl.MIN_JOB_SCHEDULER_API_LEVEL) {
scheduler = new SystemJobScheduler(context, workDatabase, configuration);
setComponentEnabled(context, SystemJobService.class, true);
Logger.get().debug(TAG, "Created SystemJobScheduler and enabled SystemJobService");
} else {
scheduler = tryCreateGcmBasedScheduler(context, configuration.getClock());
if (scheduler == null) {
scheduler = new SystemAlarmScheduler(context);
setComponentEnabled(context, SystemAlarmService.class, true);
Logger.get().debug(TAG, "Created SystemAlarmScheduler");
}
}
return scheduler;
}
- 首先,方法检查当前设备的Android版本是否高于或等于
WorkManagerImpl.MIN_JOB_SCHEDULER_API_LEVEL
(通常是API级别 23,即Android 6.0 Marshmallow)。因为从Android 6.0开始,Android引入了JobScheduler
API。 - 如果设备支持
JobScheduler
API,代码会创建一个SystemJobScheduler
实例。SystemJobScheduler
是WorkManager
的一个内部类,它通过Android的JobScheduler
服务来调度任务。同时,代码会通过setComponentEnabled
方法启用SystemJobService
类。 - 对于旧版本的Android设备,代码首先尝试创建一个基于GCM(Google Cloud Messaging)的调度器,通过
tryCreateGcmBasedScheduler
方法,依赖于Google服务。 - 如果基于GCM的调度器不能被创建(没有GMS),那么代码会回退到使用
SystemAlarmScheduler
。这个调度器通过AlarmManager
和广播接收器来调度任务,适用于旧设备,但不高效。