带有 StateFull 小部件的 Flutter WorkManager 后台获取示例

Flutter WorkManager Background Fetch Example With StateFull Widget

我在 StateFull Widget 中有一个名为 control 的函数。我想每 15 分钟 运行 使用 WorkManager 执行此功能。

如何从 callbackDispatcher 函数中调用控制函数? 我在 Statefull 小部件中静态添加了一个 Stream,然后听了它,但它没有用。

HomeScreen.dart 文件

import 'package:flutter/material.dart';
import 'package:workmanager/workmanager.dart';

const taskKontrol = "control";

class HomeScreen extends StatefulWidget {
  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  @override
  Widget build(BuildContext context) {
    return Container();
  }

  @override
  void initState() {
    super.initState();
    setupWorkManager();
  }

  void control() async
  {
    //... my code control is here
  }

}

void setupWorkManager() async {
  await Workmanager.initialize(callbackDispatcher, isInDebugMode: true);
  Workmanager.registerPeriodicTask(taskKontrol, taskKontrol,
      frequency: Duration(seconds: 10),
      existingWorkPolicy: ExistingWorkPolicy.append
  );
}


void callbackDispatcher() {
  Workmanager.executeTask((taskName, inputData) async {
    switch(taskName)
    {
      case taskKontrol:
        // How can I call the control function from here?
        print("control from workmanager");
        break;
    }
    return Future.value(true);
  });
}

对于那些仍在寻找答案的人:

来自official docs:

The callbackDispatcher needs to be either a static function or a top level function to be accessible as a Flutter entry point.

我遇到了同样的问题,我通过将函数 callbackDispatcher 移动到文件中解决了这个问题:main.dart

此外,初始化 callbackDispatcher 的代码必须在 main()App() 小部件加载之前。

要调用您的控制代码,请创建一个具有静态函数 control()

的 class

注意:您不能从 callbackDispatcher 调用小部件的方法!

原因:小部件是 UI 绑定的。只要屏幕保持活动状态,可见的小部件就会保持活动状态。一旦您关闭应用程序或移至下一个屏幕,小部件的内存就会被回收。但是即使您的应用程序关闭,此 callbackDispatcher 也会执行。因此,它必须与 UI 代码隔离。

代码如下:

main.dart:

import 'package:flutter/material.dart';
import 'package:workmanager/workmanager.dart';


void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Workmanager().initialize(callbackDispatcher, isInDebugMode: true);
  runApp(App());
}

void callbackDispatcher() {
  Workmanager.executeTask((taskName, inputData) async {
    switch(taskName)
    {
      case ScheduledTask.taskName:
        ScheduledTask.control(); // calls your control code
        break;
    }
    return Future.value(true);
  });
}

class ScheduledTask {
  const static String taskName = "control";
  static void control() {
    // add your control here
  }
}

您在 HomeScreen 小部件中所能做的就是调用 setupWorkManager() 来安排任务

class _HomeScreenState extends State<HomeScreen> {
  @override
  Widget build(BuildContext context) {
    return Container();
  }

  @override
  void initState() {
    super.initState();
    setupWorkManager();
  }
}

void setupWorkManager() async {
  Workmanager.registerPeriodicTask(taskKontrol, taskKontrol,
      frequency: Duration(minutes: 15),
      existingWorkPolicy: ExistingWorkPolicy.append
  );
}

注意:循环任务的最低频率为15分钟