我们有一个使用WorkManager处理后台同步工作的Android应用。我们的同步工作者是这样的:
public class SyncWorker extends Worker {
[...]
@NonNull
@Override
public Result doWork() {
if (canNotRetry(getRunAttemptCount())) {
// This could seem unreachable, consider removing... or not... because if stopped by the
// system, the work might be retried by design
CBlogger.INSTANCE.log([...]);
return Result.success();
}
boolean syncOk = false;
//Sync
try (Realm realm = Realm.getDefaultInstance()) {
// Doing sync related ops & network calls
// checking this.isStopped() between operations to quit
// sync activity when worker has to be stopped
syncOk = true;
} catch (Throwable throwable) {
CBlogger.INSTANCE.log([...]);
}
// On error, continue with following code to avoid any logic in catch
// This method must NOT throw any unhandled exception to avoid unique work to be marked as failed
try {
if (syncOk) {
return Result.success();
}
if (canNotRetry(getRunAttemptCount() + 1)) {
CBlogger.INSTANCE.log([...]);
return Result.success();
} else {
CBlogger.INSTANCE.log([...]);
return Result.retry();
}
} catch (Throwable e) {
CBlogger.INSTANCE.log([...]);
return Result.success();
}
}
private boolean canNotRetry(int tryNumber) {
// Check if the work has been retry too many times
if (tryNumber > MAX_SYNC_RETRY_COUNT) {
CBlogger.INSTANCE.log([...]);
return true;
} else {
return false;
}
}
@Override
public void onStopped() {
CBlogger.INSTANCE.log([...]);
}
}
通过助手类的专用方法安排工作:
public static void scheduleWorker(Context context, String syncPolicy, ExistingWorkPolicy existingWorkingPolicy){
Constraints constraints = new Constraints.Builder()
.setRequiresCharging(false)
.setRequiredNetworkType(NetworkType.CONNECTED)
.build();
Data.Builder data = new Data.Builder();
data.putString(context.getResources().getString(R.string.sync_worker_policy), syncPolicy);
Log.d(TAG, "Scheduling one-time sync request");
logger.info("Scheduling one-time sync request");
OneTimeWorkRequest oneTimeWorkRequest = new OneTimeWorkRequest.Builder
(SyncWorker.class)
.setInputData(data.build())
.setConstraints(constraints)
.setBackoffCriteria(
BackoffPolicy.LINEAR,
OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
TimeUnit.MILLISECONDS)
.build();
WorkManager.getInstance(context).enqueueUniqueWork("OneTimeSyncWorker", existingWorkingPolicy, oneTimeWorkRequest);
}
,当用户单击“同步”按钮时,或由计划每20秒运行一次并以这种方式调用帮助程序功能的其他工作人员调用时,会调用
:
SyncWorkerManager.scheduleWorker(context, context.getResources().getString(R.string.sync_worker_policy_full), ExistingWorkPolicy.KEEP);
,以使新同步仅在尚未等待或运行时才排队。请注意,同步工作策略强制要求连接的网络。
此策略完全奏效,但有时我们在日志中发现在SyncWorker启动后几秒钟(约10英寸)内调用了Worker的onStopped()
方法。
众所周知,我们从不以编程方式停止外部的特定Worker,而仅在注销过程中或在新登录之前(也安排了del定期Worker)调用WorkManager.getInstance(context).cancelAllWork();
,系统何时才能决定停止工人并调用其onStopped()
方法?
我知道它可能在以下情况下发生:
是否还有其他条件可能导致工人被阻止?像这样:
谢谢