如何观察Androidx.WorkManager链式任务各阶段的LiveData<WorkInfo>
如何观察WorkManager链式任务的每个阶段状态
嘿,这个问题我之前也碰到过,咱们一步步来拆解解决它!
首先得先搞清楚你之前两种写法为啥不行:
- 第一种写法只监听了
stageOne的WorkInfo,后面的stageTwo、stageThree、stageFour的状态变化完全没被监听,所以自然收不到后续阶段的更新。 - 第二种写法犯了个小错误:
CHAINED_UNIQUE_NAME是唯一工作的名称,不是任务的标签,你用getWorkInfosByTagLiveData()去查它肯定拿不到数据,因为任务本身没加这个标签。
接下来给你两种可行的解决方案,根据你的需求选就行:
方案一:用MediatorLiveData合并所有任务的状态流
如果你希望把所有阶段的状态变化合并成一个单一的LiveData流,方便观察者统一处理,MediatorLiveData是绝佳选择。它可以把多个LiveData的事件合并到一个流里,每个任务的状态更新都会通知到观察者。
代码示例:
public LiveData<WorkInfo> syncAll() { final OneTimeWorkRequest stageOne = new OneTimeWorkRequest.Builder(Stage_0001.class) .addTag(STAGE_1_IN_PROGRESS_TAG) .build(); final OneTimeWorkRequest stageTwo = new OneTimeWorkRequest.Builder(Stage_0002.class) .addTag(STAGE_2_IN_PROGRESS_TAG) .build(); final OneTimeWorkRequest stageThree = new OneTimeWorkRequest.Builder(Stage_0003.class) .addTag(STAGE_3_IN_PROGRESS_TAG) .build(); final OneTimeWorkRequest stageFour = new OneTimeWorkRequest.Builder(Stage_0004.class) .addTag(STAGE_4_IN_PROGRESS_TAG) .build(); // 构建并启动链式任务 mWorkManager.beginUniqueWork(CHAINED_UNIQUE_NAME, ExistingWorkPolicy.KEEP, stageOne) .then(stageTwo) .then(stageThree) .then(stageFour) .enqueue(); // 创建MediatorLiveData来合并所有任务的状态 MediatorLiveData<WorkInfo> combinedWorkState = new MediatorLiveData<>(); // 为每个任务添加状态监听源 addWorkInfoSource(combinedWorkState, stageOne.getId()); addWorkInfoSource(combinedWorkState, stageTwo.getId()); addWorkInfoSource(combinedWorkState, stageThree.getId()); addWorkInfoSource(combinedWorkState, stageFour.getId()); return combinedWorkState; } // 封装重复的添加源逻辑,减少代码冗余 private void addWorkInfoSource(MediatorLiveData<WorkInfo> mediator, UUID workId) { LiveData<WorkInfo> workInfoLiveData = mWorkManager.getWorkInfoByIdLiveData(workId); mediator.addSource(workInfoLiveData, workInfo -> { if (workInfo != null) { mediator.setValue(workInfo); // 任务完成后移除该源,避免不必要的监听 if (workInfo.getState().isFinished()) { mediator.removeSource(workInfoLiveData); } } }); }
使用的时候,观察者可以直接拿到每个阶段的WorkInfo,通过getTags()或者getId()来判断当前是哪个阶段:
syncAll().observe(this, workInfo -> { if (workInfo.getTags().contains(STAGE_1_IN_PROGRESS_TAG)) { Log.d("WorkSync", "阶段1状态:" + workInfo.getState()); } else if (workInfo.getTags().contains(STAGE_2_IN_PROGRESS_TAG)) { Log.d("WorkSync", "阶段2状态:" + workInfo.getState()); } // 其他阶段同理 });
方案二:给所有任务添加共同标签,监听标签对应的任务列表
如果希望一次性拿到所有链式任务的状态列表,可以给每个阶段的任务都添加一个共同的标签,然后通过这个标签来监听所有任务的状态变化。
代码示例:
// 定义一个所有链式任务共用的标签 private static final String SYNC_CHAIN_COMMON_TAG = "SYNC_CHAIN_COMMON_TAG"; public LiveData<List<WorkInfo>> syncAll() { final OneTimeWorkRequest stageOne = new OneTimeWorkRequest.Builder(Stage_0001.class) .addTag(STAGE_1_IN_PROGRESS_TAG) .addTag(SYNC_CHAIN_COMMON_TAG) // 添加共用标签 .build(); final OneTimeWorkRequest stageTwo = new OneTimeWorkRequest.Builder(Stage_0002.class) .addTag(STAGE_2_IN_PROGRESS_TAG) .addTag(SYNC_CHAIN_COMMON_TAG) .build(); final OneTimeWorkRequest stageThree = new OneTimeWorkRequest.Builder(Stage_0003.class) .addTag(STAGE_3_IN_PROGRESS_TAG) .addTag(SYNC_CHAIN_COMMON_TAG) .build(); final OneTimeWorkRequest stageFour = new OneTimeWorkRequest.Builder(Stage_0004.class) .addTag(STAGE_4_IN_PROGRESS_TAG) .addTag(SYNC_CHAIN_COMMON_TAG) .build(); mWorkManager.beginUniqueWork(CHAINED_UNIQUE_NAME, ExistingWorkPolicy.KEEP, stageOne) .then(stageTwo) .then(stageThree) .then(stageFour) .enqueue(); // 监听共用标签对应的所有任务状态 return mWorkManager.getWorkInfosByTagLiveData(SYNC_CHAIN_COMMON_TAG); }
观察者收到的是List<WorkInfo>,可以遍历列表逐个处理每个阶段的状态:
syncAll().observe(this, workInfos -> { for (WorkInfo info : workInfos) { if (info.getTags().contains(STAGE_1_IN_PROGRESS_TAG)) { Log.d("WorkSync", "阶段1状态:" + info.getState()); } else if (info.getTags().contains(STAGE_2_IN_PROGRESS_TAG)) { Log.d("WorkSync", "阶段2状态:" + info.getState()); } // 处理其他阶段... } });
这两种方案都能完美解决你的问题,选哪种取决于你更倾向于单一状态流还是批量处理状态列表~
内容的提问来源于stack exchange,提问作者Hector
相关产品推荐
相关产品推荐

