fluttercommunity / flutter_workmanager

A Flutter plugin which allows you to execute code in the background on Android and iOS.
825 stars 247 forks source link

🐞[Unexpected Widget Rebuilds when Using WorkManager] #522

Closed AvetisyanYuri closed 5 months ago

AvetisyanYuri commented 7 months ago

Version | Workmanager version | 0.5.2 | Android studio version | Android Studio Giraffe | 2022.3.1 Patch 3 | Flutter version | 3.16.0 | Dart version | 3.2.0

I'm experiencing unexpected widget rebuilds when using the WorkManager plugin in my Flutter app. Specifically, every time I call Workmanager().registerOneOffTask, it triggers a rebuild of the entire widget tree, including the MyApp widget. Optionally provide the least amount of code that shows this behaviour. Ideally in the sample app.

Expected Behavior

I expect that scheduling a one-off task using WorkManager on Android should not trigger a rebuild of the entire widget tree.

Actual Behavior

The MyApp widget, and potentially others, are being rebuilt every time registerOneOffTask is called on Android.

Flutter doctor

[✓] Flutter (Channel stable, 3.16.0, on Ubuntu 22.04.3 LTS 6.2.0-36-generic, locale en_US.UTF-8) • Flutter version 3.16.0 on channel stable at /home/yuri/snap/flutter/common/flutter • Upstream repository https://github.com/flutter/flutter.git • Framework revision db7ef5bf9f (19 hours ago), 2023-11-15 11:25:44 -0800 • Engine revision 74d16627b9 • Dart version 3.2.0 • DevTools version 2.28.2

[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0) • Android SDK at /home/yuri/Android/Sdk • Platform android-34, build-tools 34.0.0 • Java binary at: /home/yuri/.local/share/JetBrains/Toolbox/apps/android-studio/jbr/bin/java • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b829.9-10027231) • All Android licenses accepted.

[✓] Chrome - develop for the web • Chrome at google-chrome

[✓] Linux toolchain - develop for Linux desktop • clang version 10.0.0-4ubuntu1 • cmake version 3.16.3 • ninja version 1.10.0 • pkg-config version 0.29.1

[✓] Android Studio (version 2022.3) • Android Studio at /home/yuri/.local/share/JetBrains/Toolbox/apps/android-studio • Flutter plugin version 76.3.2 • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b829.9-10027231)

[✓] VS Code (version unknown) • VS Code at /snap/code/current • Flutter extension can be installed from: 🔨 https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter ✗ Unable to determine VS Code version.

[✓] Connected device (3 available) • sdk gphone64 x86 64 (mobile) • emulator-5554 • android-x64 • Android 14 (API 34) (emulator) • Linux (desktop) • linux • linux-x64 • Ubuntu 22.04.3 LTS 6.2.0-36-generic • Chrome (web) • chrome • web-javascript • Google Chrome 119.0.6045.159

[✓] Network resources • All expected network resources are available.

• No issues found!

Code

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

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

void main() { WidgetsFlutterBinding.ensureInitialized(); Workmanager().initialize( callbackDispatcher, // The top level function, aka callbackDispatcher isInDebugMode: true // If enabled it will post a notification whenever the task is running. Handy for debugging tasks ); runApp(const MyApp()); }

class MyApp extends StatelessWidget { const MyApp({super.key});

@override Widget build(BuildContext context) { print('[BUILD] MyApp'); return MaterialApp( title: 'Flutter Demo', theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true, ), home: const MyHomePage(title: 'Flutter Demo Home Page'), ); } }

class MyHomePage extends StatelessWidget { const MyHomePage({super.key, required this.title});

final String title;

@override Widget build(BuildContext context) { print('[BUILD] MyHomePage'); return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, title: Text(title), ), body: const Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( 'Register task', ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: () { final taskIdentifier = const Uuid().v4(); Workmanager().registerOneOffTask( taskIdentifier, "simpleTask" ); }, tooltip: 'Register task', child: const Icon(Icons.add), ), // This trailing comma makes auto-formatting nicer for build methods. ); } }

`

Output

image

AccioHorcrux commented 6 months ago

same issue occurred in my application as well. Every time Work Manager runs full application rebuild itself and because of that i am not able to maintain the proper state of the application. It affects in every StateFull Widget and rebuilds init() method after every interval of time. In my case happening for Periodic Services that runs every 15 Mins. What needs to be done here, does anyone knows ?

pichillilorenzo commented 6 months ago

same issue here, @ened any news about this problem? thanks.

Currently, this plugin is not usable as it reloads the whole App every time you want to register a task. I'm using Flutter 3.16.1

AvetisyanYuri commented 5 months ago

It seems the issue was with the emulator API version. I was using API 34, but when I changed it to API 29, everything worked. There are no more issues.

Tomaz-Kobal commented 2 months ago

This is still an issue with API 34 phones and emulators.

vanlooverenkoen commented 1 month ago

@Tomaz-Kobal I don't have this on my Pixel 8 Pro. Is this really still an issue?

AccioHorcrux commented 1 month ago

@vanlooverenkoen issue still persist and unable to find any solution. Play store requires minimum API 34 and we have used workmanager in Production Released App and because of this issue we are going to remove workmanage. It does not happen frequently so not many user faced it but its still a matter of concern.

vanlooverenkoen commented 1 month ago

But I feel like this is a flutter issue, not a workmanager issue. I have something similar one in our background_location tracker: https://github.com/icapps/flutter-background-location-tracker/issues/68

AccioHorcrux commented 1 month ago

Okk @vanlooverenkoen ... Looks like happening with things that are related with Background Services in Flutter

vanlooverenkoen commented 1 month ago

I feel like something is going wrong when using

@pragma('') and setting a backgroundCallback.

The rebuild only happens when you call a method channel inside the backgroundCallback function itself.

If you leave the backgroundCallback empty (only a print). it works just fine. (meaning you don't call Workmanager().initialize()

vanlooverenkoen commented 1 month ago

@AccioHorcrux which architecture & development machine are you using?

vanlooverenkoen commented 1 month ago

@AccioHorcrux can you confirm you have the issue on a release & debug build?

vanlooverenkoen commented 1 month ago

@AccioHorcrux are you using visual studio code, commandline or android studio to run/build your app?

vanlooverenkoen commented 1 month ago

We found that if you do flutter run in the commandline in android studio it works. If you run it through android studio it does not work and rebuilds on every update.

AccioHorcrux commented 1 month ago

@vanlooverenkoen I use android studio and issue occurs mostly on debug build and no one report such incident on release build yet, for project architecture i am using BLOC.

vanlooverenkoen commented 1 month ago

@AccioHorcrux How are you building the release builds? Through the cli? because that would make sense. The bug is located in android studio. The moment you run flutter run or flutter build it works fine. Can you try switching to visual studio code to test if everything works fine there? This is how we are currenlty handling the issue. (using vs code)