Android源码阅读WorkMangaer - 4

前言

由于笔者目前水平限制,表达能力有限,尽请见谅。

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习惯的接口,或者解决可能的命名冲突。

他干了什么?

  1. 实例化WorkManagerImpl:使用给定的ConfigurationContext,以及可选的TaskExecutor(如果没有提供,则使用默认的),创建WorkManagerImpl的实例。WorkManagerImplWorkManager抽象类的实现,负责实际的工作调度和执行逻辑。

  2. 构建WorkDatabase:这个数据库用于存储所有的工作请求信息和状态。WorkDatabase.create方法根据提供的ConfigurationTaskExecutor构建数据库实例。

  3. 创建TrackersProcessor:这些组件用于跟踪工作的状态和执行工作。Trackers负责监听系统条件的变化,Processor则负责处理和执行工作请求。

  4. 调度器:根据配置和环境,选择和创建最合适的调度器(Scheduler)实例。调度器负责决定何时以及如何执行工作,例如,它可能决定在设备充电时执行某项工作,或者在满足特定的网络条件时执行。

  5. 返回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表示一个函数类型,这个函数接收一系列参数(ContextConfiguration等)并返回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
        ),

做了以下两件事:

  1. 调用Schedulers.createBestAvailableBackgroundScheduler

    尝试创建最适合当前设备条件的后台任务调度器。
  2. 创建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;
    }
  1. 首先,方法检查当前设备的Android版本是否高于或等于WorkManagerImpl.MIN_JOB_SCHEDULER_API_LEVEL(通常是API级别 23,即Android 6.0 Marshmallow)。因为从Android 6.0开始,Android引入了JobScheduler API。
  2. 如果设备支持JobScheduler API,代码会创建一个SystemJobScheduler实例。SystemJobSchedulerWorkManager的一个内部类,它通过Android的JobScheduler服务来调度任务。同时,代码会通过setComponentEnabled方法启用SystemJobService类。
  3. 对于旧版本的Android设备,代码首先尝试创建一个基于GCM(Google Cloud Messaging)的调度器,通过tryCreateGcmBasedScheduler方法,依赖于Google服务。
  4. 如果基于GCM的调度器不能被创建(没有GMS),那么代码会回退到使用SystemAlarmScheduler。这个调度器通过AlarmManager和广播接收器来调度任务,适用于旧设备,但不高效。

  • 25
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏目艾拉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值