应用场景之一,免费电子书退出app后,后台定时从web爬取小说最新内容实现自动更新!
这里使用的是一个开源软件BackgroundFetch。BackgroundFetch的sample代码中没有太多解析,所以看起来有写费劲,这里就例子做简要说明。
BackgroundFetch其实可以分为两部分,一部分是APP退出后在后台运行的叫做HeadlessTask,一个是进入APP后再后台运行的,叫BackgroundFetch。对于sample中的代码,我们把它划分成两部分来看就简单了。
- HeadlessTask
这部分任务是在APP退出后周期性运行的,代码中配置如下:
import 'package:background_fetch/background_fetch.dart';
/// This "Headless Task" is run when app is terminated.
void backgroundFetchHeadlessTask(String taskId) async {
DateTime timestamp = DateTime.now();
print("[BackgroundFetch] Headless event received: $taskId@$timestamp");
BackgroundFetch.finish(taskId);
if (taskId == 'flutter_background_fetch') {
await AutoRefresh.fetchAndUpdateAllBooks();
}
}
void main() {
runApp(MyApp());
// Register to receive BackgroundFetch events after app is terminated.
// Requires {stopOnTerminate: false, enableHeadless: true}
BackgroundFetch.registerHeadlessTask(backgroundFetchHeadlessTask);
}
flutter_background_fetch是BackgroundFetch默认的TaskID(的名称),只要运行BackgroundFetch,默认就有个taskid = flutter_background_fetch的任务在运行(这涉及到BackgroundFetch的配置,可以看下节)。运行的间隔时间由下届=节中提到的初始config决定,一般在Android时间比较准确,IOS中由于平台的运行,可能不是很准。
代码说明:main中注册HeadlessTask,然后实际运行时就会跑backgroundFetchHeadlessTask,默认taskid为flutter_background_fetch。代码中的AutoRefresh.fetchAndUpdateAllBooks()就是我项目中对电子书的刷新。
- BackgroundFetch
这部分task则是进入app后,在后台运行的,看代码:
@override
void initState() {
super.initState();
loadData();
initPlatformState();
}
Future<void> initPlatformState() async {
BackgroundFetch.configure(BackgroundFetchConfig(
minimumFetchInterval: 60,
forceAlarmManager: true,
stopOnTerminate: false,
startOnBoot: true,
enableHeadless: true,
requiresBatteryNotLow: true,
requiresCharging: false,
requiresStorageNotLow: true,
requiresDeviceIdle: false,
requiredNetworkType: NetworkType.UNMETERED,
), _onBackgroundFetch).then((int status){
print('[BackgroundFetch] configure success: $status');
}).catchError((e) {
print('[BackgroundFetch] configure ERROR: $e');
});
/*BackgroundFetch.scheduleTask(TaskConfig(
taskId: "com.transistorsoft.customtask",
delay: 10000,
periodic: false,
forceAlarmManager: true,
stopOnTerminate: false,
enableHeadless: true
));*/
}
void _onBackgroundFetch(String taskId) async {
DateTime timestamp = DateTime.now();
print("[BackgroundFetch] Event received: $taskId@$timestamp");
if (taskId == "flutter_background_fetch") {
// Schedule a one-shot task when fetch event received (for testing).
BackgroundFetch.scheduleTask(TaskConfig(
taskId: "com.transistorsoft.customtask",
delay: 5000,
periodic: false,
forceAlarmManager: true,
stopOnTerminate: false,
enableHeadless: true
));
}
// IMPORTANT: You must signal completion of your fetch task or the OS can punish your app
// for taking too long in the background.
BackgroundFetch.finish(taskId);
}
BackgroundFetch.configure就是对默认任务flutter_background_fetch的配置, minimumFetchInterval就是时间间隔,APP运行的情况下,对任务flutter_background_fetch的处理函数是configure中的_onBackgroundFetch,例如上述代码,每隔1个小时就会调用一次_onBackgroundFetch, 而当APP退出后,每隔一个小时,会跑一次backgroundFetchHeadlessTask。代码中的BackgroundFetch.scheduleTask是自定义的任务。
- 总结
一直在找可以实现后台定时任务的的Dart API,目前只找到这个,问题暂时没发现。