The getter 'userGestureInProgress' was called on null

Viewed 1296

I am creating an app for children. It has menu screen from where you can go to different games by clicking an appropriate button. When game is completed a star animation starts. When animation is finished I want my app return back to menu screen. Here is the problem. When the animation finishes I get this error: The getter 'userGestureInProgress' was called on null. Also there is no stack trace so I can not identify where exactly this error happens.

Here is my code:

class OddOneOutPage extends StatefulWidget {
 @override
 State<StatefulWidget> createState() {
 return OddOneOutPageState();
 }
}

class OddOneOutPageState extends State<OddOneOutPage>
with SingleTickerProviderStateMixin {
  Widget _pageContent;
  ValueNotifier<bool>_animationFinished;
  Particles particles;
  bool _gameFinished = false;

  @override
  void initState() {
    super.initState();
   _animationFinished = ValueNotifier(false);

   _animationFinished.addListener(() {
      if(_animationFinished.value) {
        Navigator.pop(context); // this line causes a problem
      }
   });

   particles = Particles(30, _animationFinished);
  }

  @override
  Widget build(BuildContext context) {
    Widget body;

  // some code to check if game is finished

    if (_gameFinished) {
      body = Stack(
        children: <Widget>[
          AnimatedSwitcher(
            duration: Duration(milliseconds: 300),
            child: _pageContent,
          ),
          Positioned.fill(child: particles)
        ],
      );
    } else {
      body = AnimatedSwitcher(
          duration: Duration(milliseconds: 300), child: _pageContent);
    }
    return Scaffold(
      appBar: AppBar(
        title: Text(MyLocalizations.of(context, StringKeys.oddOneOut)),
      ),
      body: body,
    ),
  );
}

Here is logs with exception:

════════ Exception caught by animation library ═══════════════════════

The following assertion was thrown while notifying status listeners for AnimationController:
Build scheduled during frame.

While the widget tree was being built, laid out, and painted, a new frame was scheduled to rebuild the widget tree. This might be because setState() was called from a layout or paint callback. If a change is needed to the widget tree, it should be applied as the tree is being built. Scheduling a change for the subsequent frame instead results in an interface that lags behind by one frame. If this was done to make your build dependent on a size measured at layout time, consider using a LayoutBuilder, CustomSingleChildLayout, or CustomMultiChildLayout. If, on the other hand, the one frame delay is the desired effect, for example because this is an animation, consider scheduling the frame in a post-frame callback using SchedulerBinding.addPostFrameCallback or using an AnimationController to trigger the animation.
When the exception was thrown, this was the stack: 
0  WidgetsBinding._handleBuildScheduled.<anonymous closure> (package:flutter/src/widgets/binding.dart:637:9)
1      WidgetsBinding._handleBuildScheduled (package:flutter/src/widgets/binding.dart:656:6)
2      BuildOwner.scheduleBuildFor (package:flutter/src/widgets/framework.dart:2232:7)
3      Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:3706:11)
4      State.setState (package:flutter/src/widgets/framework.dart:1161:14)
...
The AnimationController notifying status listeners was: AnimationController#677b4(◀ 1.000; for MaterialPageRoute<dynamic>(null))
════════════════════════════════════════════════════════════════════════════════════════════════════

════════ (2) Exception caught by widgets library ═══════════════════════════════════════════════════
The getter 'userGestureInProgress' was called on null.
Receiver: null
Tried calling: userGestureInProgress
User-created ancestor of the error-causing widget was: 
  MaterialApp file:///C:/Users/olgam/Desktop/FlutterProjects/Projects/Kids%20Development/kids_development/lib/main.dart:10:12
══════════════════════════════════════════════════════════════

Here is Flutter Doctor result:

[√] Flutter (Channel stable, v1.9.1+hotfix.4, on Microsoft Windows [Version 10.0.18362.418], locale en-US)
    • Flutter version 1.9.1+hotfix.4 at C:\Users\olgam\source\flutter
    • Framework revision cc949a8e8b (4 weeks ago), 2019-09-27 15:04:59 -0700
    • Engine revision b863200c37
    • Dart version 2.5.0

[√] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
    • Android SDK at C:\Users\olgam\AppData\Local\Android\sdk
    • Android NDK location not configured (optional; useful for native profiling support)
    • Platform android-28, build-tools 28.0.3
    • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b03)
    • All Android licenses accepted.

[√] Android Studio (version 3.5)
    • Android Studio at C:\Program Files\Android\Android Studio
    • Flutter plugin version 40.2.2
    • Dart plugin version 191.8593
    • Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b03)

[√] Connected device (1 available)
    • Android SDK built for x86 • emulator-5554 • android-x86 • Android 7.0 (API 24) (emulator)

• No issues found!
1 Answers

Well, hard to tell exactly, because evidently not all your code is shown. But I cannot see where you push something into the Navigator's views stack. I see you are popping from the navigator, but it is not shown in your code if you actually push something there before.

Also for me it looks like you are not using the AnimatedSwitcher correctly. This widget presumes that its child can change and when the child is changed then it applies an animation so the transition between old and new child looks "nice". And in your code you just use two different instances of the AnimatedSwitcher depending on the _gameFinished value. Try to think this over and change your implementation and I hope it helps.

Related