在使用workmanager插件时,需要初始化和注册。初始化时,需要传递一个静态或者顶级函数callbackDispatcher()
。
@pragma('vm:entry-point') // Mandatory if the App is obfuscated or using Flutter 3.1+
void callbackDispatcher() {
Workmanager().executeTask((task, inputData) {
print("Native called background task: $task"); //simpleTask will be emitted here.
return Future.value(true);
});
}
/// main函数中初始化
main(){
Workmanager().initialize(
callbackDispatcher, // The top level function, aka callbackDispatcher
isInDebugMode: kDebugMode // If enabled it will post a notification whenever the task is running. Handy for debugging tasks
);
}
/// 注册周期性任务 至少15分钟一个周期
Workmanager().registerPeriodicTask(
"periodic-task-identifier",
"simplePeriodicTask",
inputData: <String, dynamic>{
'key': 'value',
},
// When no frequency is provided the default 15 minutes is set.
// Minimum frequency is 15 min. Android will automatically change your frequency to 15 min if you have configured a lower frequency.
frequency: const Duration(minutes: 15),
);
我们在callbackDispatcher()
这个函数中处理任务时,例如同步eventbus
发送一个消息到某个页面,此时时无法收到消息的。原因是:The workmanager runs on a separate isolate from the main flutter isolate. Ensure to initialize all dependencies inside the Workmanager().executeTask.
他们处于不同的isolate中,所以无法收到消息。
解决办法:借助isolate间通信来实现消息传递。在main()中创建主Isolate,并实现监听,接受其他Isolate发来的消息,在顶级函数中发送Isolate消息。
import 'package:flutter/material.dart';
import 'package:workmanager/workmanager.dart';
void callbackDispatcher() {
Workmanager().executeTask((task, inputData) async {
// 创建一个 ReceivePort 用于接收主 isolate 的消息
ReceivePort receivePort = ReceivePort();
// 发送消息到主 isolate
IsolateNameServer.lookupPortByName('main_isolate')?.send('Hello from Workmanager');
// 返回任务执行结果
return Future.value(true);
});
}
void main() {
WidgetsFlutterBinding.ensureInitialized();
// 初始化 Workmanager
Workmanager().initialize(callbackDispatcher, isInDebugMode: true);
// 注册一个周期性任务
Workmanager().registerPeriodicTask(
'1',
'simpleTask',
frequency: Duration(hours: 1),
);
// 注册主 isolate 的 SendPort
ReceivePort mainReceivePort = ReceivePort();
IsolateNameServer.registerPortWithName(mainReceivePort.sendPort, 'main_isolate');
// 监听来自 Workmanager 的消息
mainReceivePort.listen((message) {
// 通过 eventbus 发送消息
eventBus.fire(MyEvent(message));
});
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String _message = 'No message yet';
@override
void initState() {
super.initState();
// 监听 eventbus
eventBus.on<MyEvent>().listen((event) {
setState(() {
_message = event.message;
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Workmanager Eventbus Example'),
),
body: Center(
child: Text(_message),
),
);
}
}
Android 限制:
在 Android 6.0 (API 23) 及更高版本中,操作系统会对后台任务进行严格限制,以节省电池寿命。这些限制包括最小周期时间和对后台任务的管理策略。
Android 的 JobScheduler API(以及相应的 WorkManager 库)对周期性任务的最小间隔时间进行了限制。即使你设置了一个小时的频率,系统可能会根据其策略将其调整为更频繁的执行时间。
WorkManager 最小周期:
Android WorkManager 的文档中提到,最小周期性时间间隔通常是15 分钟
。这意味着即使你在 Workmanager 插件中设置了 1 小时的间隔,系统仍然可能每 15 分钟执行一次任务。
网友评论