Cannot compile SchedulerBinding.instance.addPostFrameCallback and executeAfterBuild() async not working either - flutter

In my app the user is presented with a puzzle, drawn by a re-implementation of Flutter's CustomerPainter class and accepting moves made by tapping on the Canvas. The Canvas is continually updated and re-drawn to show the moves. When the user makes the last move and completes a correct solution, the app should tell the user so. The app is using Flutter's AlertDialog to issue such messages to the user.
The problem is that the app is deep in the paint() method of CustomPainter when a solution situation is detected. Any attempt to issue a message at that point crashes the app. The message to the user does appear, but by that time the app has crashed. The error messages are either:
[ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception:
setState() or markNeedsBuild() called during build.
or
[ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception:
Build scheduled during frame.
These messages are followed by comprehensive advice as to what has happened and what to do. There are also several suggestions on Stack Overflow, but I cannot get any of them to work.
If I write SchedulerBinding.instance.addPostFrameCallback in my widget-build it fails to compile because it wants several parts from BindingBase. SchedulerBinding is a mixin. If I try to mixin BindingBase to my Widget, compilation fails again because BindingBase is a class, with a constructor, not a mixin.
If I go the async way, using Future executeAfterBuild(), the app compiles but crashes again, apparently because the async function executes straight away (as is normal) and is not scheduled after the widget-build, as suggested in some of the Stack Overflow posts. The app is definitely not in setState() when it crashes, so maybe marksNeedsBuild() is triggering the crash somehow.
I am using Flutter 2.8.2 and Dart 2.15.1, plus sound null safety. Has Flutter's widget-scheduling policy changed? The Stack Overflow posts I refer to are up to 3 years old.

have you tried putting setState in :
WidgetsBinding.instance?.addPostFrameCallback((_) {setState((){});})

Related

How can I use Navigator in onBackgroundMessageHandler of Firebase in killed state in Flutter?

I have developed a flutter app where it has calling feature with Agora SDK. In the latest version of firebase_messaging package, the method onBackgroundMessageHandler is made a separate isolate which will have its own context and memory.
Isolates should be
Top level methods or
Static methods inside the class.
when onBackgroundMessageHandler is made top-level function, the method doesn't get called in killed state in release mode. The solution for release mode issue is being solved as per most of the solutions provided by the flutter community.
The solution is to use #pragma like below
#pragma('vm:entry-point')
Future<void> onBackgroundMessageHandler(RemoteMessage message){}
This #pragma('vm:entry-point') is used to indicate the compiler that this method will be used from native code.
Using #pragma('vm:entry-point') poses an issue of not able to access the navigator context to show the incoming call.
Libraries used to achieve calling feature
Agora SDK for voice calling : agora_rtc_engine
Flutter Incoming Call for calling notification : flutter_incoming_call
GetX for navigation: get
Problems
Adding #pragma('vm:entry-point') does not provide Navigator in killed state to push a new screen.
Not Adding #pragma('vm:entry-point') does not work in the killed state.
I'm using flutter_incoming_call for showing the calling notification where I'm showing "Accept" and "Decline" buttons. Tapping on "Accept" button somehow I'm able to navigate to Incoming call screen but the next time when I'm trying to navigate to any screen without relaunching the app, throws an error as below
You are trying to use contextless navigation without
a GetMaterialApp or Get.key.
If you are testing your app, you can use:
[Get.testMode = true], or if you are running your app on
a physical device or emulator, you must exchange your [MaterialApp]
for a [GetMaterialApp].
I tried replacing this with global key implementation.
GlobalKey<NavigationState> navigatorKey = GlobalKey<NavigationState>();
This gives navigorKey.currentState as null.
I would need the help from Flutter community to resolve this issue of navigating to any screen from killed state in onBackgroundMessageHandler method of firebase.
If there are any other solutions, I'd like to hear them too. Please provide any suggestions.

Flutter : Unable to navigate to next screen getting consider canceling any active work during "dispose" or using the "mounted"

when i am trying to navigate screen i am getting this error
Error is this
consider canceling any active work during "dispose" or using the "mounted"
on line 81 write if(mounted){ //your code }
i suspect the issue is with the widget being already disposed, look at the line before this
flutter (11689): Consider canceling
in your log, it says the widget was already unmounted and you're trying to access the context,
also consider using this instead of timer (which i also suspect is causing an issue)
await Future.delayed(Duration(seconds:3))
then navigating

Flutter InappWebView canGoBack - no implementation found for method

I am developing navigation to the previous pages for my flutter browser app, and to do this I am using goBack and goForward methods of InAppWebViewController.
To check whether I can go back (to change color of navigation buttons) I also call canGoBack method. As it returns Future, I am using FutureBuilder to display these icons.
I propagate canGoBack() or canGoForward() to the future field of FutureBuilder. And then a lot of strange thigs happen: sometimes when I switch between different tabs (which work similar to tabs in https://github.com/pichillilorenzo/flutter_browser_app) I receive:
MissingluginException: No implementation for method canGoForward on channel com.pichillilorenzo/flutter_inappwebview_n, where n is some number
Bug usually occur when I pop back to the widget with buttons and InAppWebView from tabs page.
I've searched all related github issues and haven't found anything related, tested on android(emulator + real device), iOS (simulator + real device) - and I cannot even see the pattern of how to reproduce this bug.
So, I have several questions:
What may be the reasons for this to happen? At first glance, it happens at random moments
What 'channel' exactly means here? I would be glad to read more about that
May it be caused because I use FutureBuilder?

Trace setState calls in Flutter

I am having an issue in my app with constant rebuilds. I guess there is some side effect that triggers setState.
Is there a way to trace all setState calls in the whole app?
flutter has amazing tools to handle all kind of stuff and specific what you want. Take a look at: https://flutter.dev/docs/development/tools/devtools/overview

How should I tell flutter that my app needs rebuilding externally?

I want my app to get an intent, and depending on the intent to display something in the app.
Normally, when a widget depends on state, you put it in a State and run setState().
The issue is that when I try starting my flutter app with different intents, I just get I/FlutterActivityDelegate( 4472): onResume setting current activity to this. And in a way it makes sense - I'm not saying anywhere in the flutter code that my widget needs repainting - since I get my intent through Java.
On the other hand, there should be a way to tell flutter to repaint my widget by intent? Or is there something else I should do?
Specifically to get notified about onResume event you can use WidgetsBindingObserver. Implement its didChangeAppLifecycleState method and respond to AppLifecycleState.resumed by doing whatever it is you want the UI to do, such as call setState to trigger rebuild. That said, there needs to be an effective change for the UI to be repainted. Simply calling setState with no effective state change may not result (in fact, should not) in actual UI changes.
In general, you can send a message from Java (or Objective-C/Swift) to Flutter using BasicMessageChannel and make your app react to the message (e.g. call setState or schedule frames).