Flutter WorkManager Background Fetch Example With StateFull Widget

5.2k views Asked by At

I have a function called control in the StateFull Widget. I want to run this function with WorkManager every 15 minutes.

How can I call the control function from the callbackDispatcher function? I added a Stream statically to the Statefull widget and then listened to it but it didn't work.

HomeScreen.dart file

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);
  });
}
1

There are 1 answers

0
rehman_00001 On BEST ANSWER

For those who still looking for an answer:

From the official docs:

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

I had this same problem and I solved it by moving the function callbackDispatcher to the file: main.dart

Also, the code that initializes callbackDispatcher must be in main() before the App() widget loads.

To call your control code, create a class with static function control()

Note: You cannot call the widget's method from callbackDispatcher!

Reason: Widgets are UI bound. As long as the screen remains active, the widget that is visible remains active. Once you close the app or move on to next screen, the widgets' memory gets recycled. But this callbackDispatcher gets executed even when your app is closed. So, it has to be isolated from UI code.

Here's the code:

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
  }
}

All you can do from HomeScreen widget is to call setupWorkManager() that schedules the task

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
  );
}

Note: The minimum frequency for the recurring task is 15 minutes