他们在每天早上1点到凌晨2点之间让Evernote的android-job运行工作的模式是什么?
我认为在我的Application.onCreate
和Job.onRunJob
// use the current time to see how long it will be until 1AM
long timeUntil1Am = getTimeUntil1Am(currentUnixTimeStamp);
new JobRequest.Builder(DemoSyncJob.TAG)
.setExecutionWindow(timeUntil1Am, timeUntil1Am + 3600_000L)
.setBackoffCriteria(5_000L, JobRequest.BackoffPolicy.EXPONENTIAL)
.setRequiresCharging(true)
.setRequiresDeviceIdle(false)
.setRequiredNetworkType(JobRequest.NetworkType.CONNECTED)
.setRequirementsEnforced(true)
.setPersisted(true)
.setUpdateCurrent(true)
.build()
.schedule();
它将在创建时的应用程序的第一个上午1点运行作业,然后使用onRunJob
以菊花链形式连接下一个运行时。
我认为这会有效,但我担心这项工作会多次安排,因为每次构建Application
时都会创建一个新工作。如果我知道这份工作已经安排好了,我可以避免这种情况,但不确定是否可以。
所以我的问题是使用这个菊花链是一个合理的模式,我如何避免每天多次运行这个工作?
答案 0 :(得分:1)
我使用了类似于@CommonsWare提到的FAQ中的模式
为了使这更容易,我创建了一个包装类来获取每日执行窗口
class DailyExecutionWindow {
final long startMs;
final long endMs;
/**
* Holds the start end time in ms for a job.
* Will wrap around to next day if currentHour < targetHour.
* If the current time is exactly now it will be forced to 60 seconds in the future.
*
* @param currentHour - current currentHour
* @param currentMinute - current currentMinute
* @param targetHour - currentHour we want to start
* @param targetMinute - currentMinute we want to start
* @param windowLengthInMinutes - number of minutes for the execution window
*/
DailyExecutionWindow(int currentHour, int currentMinute, long targetHour, long targetMinute, long windowLengthInMinutes) {
long hourOffset;
long minuteOffset;
if (targetHour == currentHour && targetMinute < currentMinute) {
hourOffset = TimeUnit.HOURS.toMillis(23);
} else if (targetHour - currentHour == 1) { // if we are less then an hour ahead, but into the next hour
// move forward to 0 minute of next hour
hourOffset = TimeUnit.MINUTES.toMillis(60 - currentMinute);
currentMinute = 0;
} else if (targetHour >= currentHour) {
hourOffset = TimeUnit.HOURS.toMillis(targetHour - currentHour);
} else {
hourOffset = TimeUnit.HOURS.toMillis((24 + targetHour) - currentHour);
}
if (targetMinute >= currentMinute) {
minuteOffset = TimeUnit.MINUTES.toMillis(targetMinute - currentMinute);
} else {
minuteOffset = TimeUnit.MINUTES.toMillis((60 + targetMinute) - currentMinute);
}
this.startMs = Math.max(hourOffset + minuteOffset, 60000);
this.endMs = this.startMs + TimeUnit.MINUTES.toMillis(windowLengthInMinutes);
}
}
Job
实施public class UpdateFeedsJob extends Job {
public static final String TAG = UpdateFeedsJob.class.getName();
private static final long TARGET_HOUR = 2L;
private static final long TARGET_MINUTE = 15;
private static final long WINDOW_LENGTH = 60;
private static final int WAKE_LOCK_AWAIT_TIME_SECONDS = 60;
// called in <MyApplication extends Application>.onCreate()
public static void schedule() {
schedule(true);
}
private static void schedule(boolean updateCurrent) {
Calendar calendar = Calendar.getInstance();
int hour = calendar.get(Calendar.HOUR_OF_DAY);
int minute = calendar.get(Calendar.MINUTE);
DailyExecutionWindow executionWindow =
new DailyExecutionWindow(hour, minute, TARGET_HOUR, TARGET_MINUTE, WINDOW_LENGTH);
new JobRequest.Builder(UpdateFeedsJob.TAG)
.setExecutionWindow(executionWindow.startMs, executionWindow.endMs)
.setPersisted(true)
.setUpdateCurrent(updateCurrent)
.build()
.schedule();
}
@NonNull
@Override
protected Result onRunJob(Params params) {
try {
// ... do work
return Result.SUCCESS;
} finally {
schedule(false);
}
return Result.FAILURE;
}
}
您可以在我的Podcast播放器应用on github
中看到一个有效的示例答案 1 :(得分:0)
接受的答案中的样本看起来不错。请注意,版本1.2.0将有helper class每天运行作业。