Flutter workmanager 定时任务收不到消息

在使用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 分钟执行一次任务。

最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容