首页 > 解决方案 > Flutter AnimatedBuilder 构建器错误

问题描述

以下示例代码做了一些意想不到的事情:

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    print(' *** _MyHomePageState:_incrementCounter - ${this.hashCode}');

    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Animated Text Kit Issue 168')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            AnimatedTextKit(
              animatedText: TypewriterAnimatedText(
                'Animated Text',
                textStyle: const TextStyle(
                  fontSize: 45.0,
                  fontWeight: FontWeight.w900,
                  color: Colors.pink,
                ),
              ),
            ),
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

/// Animated Text that displays a [Text] element as if it is being typed one
/// character at a time.
class TypewriterAnimatedText {
  /// Text for [Text] widget.
  final String text;

  /// [TextStyle] property for [Text] widget.
  final TextStyle textStyle;

  /// The [Duration] of the delay between the apparition of each characters
  ///
  /// By default it is set to 30 milliseconds.
  final Duration speed;

  /// The Duration for the Animation Controller.
  final Duration duration;

  /// Same as [text] but as [Characters].
  ///
  /// Need to use character length, not String length, to propertly support
  /// Unicode and Emojis.
  final Characters textCharacters;

  TypewriterAnimatedText(
    this.text, {
    @required this.textStyle,
    this.speed = const Duration(milliseconds: 30),
  })  : assert(null != speed),
        textCharacters = text.characters,
        duration = speed * (text.characters.length);

  Animation<int> _typewriterText;

  void initAnimation(AnimationController controller) {
    print(' >>> TypewriterAnimatedText:initAnimation - ${this.hashCode}');
    _typewriterText = StepTween(
      begin: 0,
      end: textCharacters.length,
    ).animate(controller);
  }

  /// Widget showing partial text
  Widget animatedBuilder(BuildContext context, Widget child) {
    print(' >>> TypewriterAnimatedText:animatedBuilder - ${this.hashCode}');
    final typewriterValue = _typewriterText.value;
    final visibleString = '${textCharacters.take(typewriterValue)}_';
    return Text(visibleString, style: textStyle);
  }
}

/// Base class for Animated Text widgets.
class AnimatedTextKit extends StatefulWidget {
  /// Text animation.
  final TypewriterAnimatedText animatedText;

  const AnimatedTextKit({
    Key key,
    @required this.animatedText,
  }) : super(key: key);

  /// Creates the mutable state for this widget. See [StatefulWidget.createState].
  @override
  _AnimatedTextKitState createState() => _AnimatedTextKitState();
}

class _AnimatedTextKitState extends State<AnimatedTextKit>
    with TickerProviderStateMixin {
  AnimationController _controller;

  @override
  void initState() {
    print(' ^^^ _AnimatedTextKitState:initState - ${this.hashCode}');
    super.initState();

    final animatedText = widget.animatedText;

    _controller = AnimationController(
      duration: animatedText.duration,
      vsync: this,
    );

    animatedText.initAnimation(_controller);

    _controller.repeat();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    print(' ^^^ _AnimatedTextKitState:build - ${this.hashCode}');

    return AnimatedBuilder(
      animation: _controller,
      builder: widget.animatedText.animatedBuilder,
    );
  }
}

运行它并单击浮动操作按钮以增加计数器,输出将如下所示:

I/flutter (29275):  ^^^ _AnimatedTextKitState:initState - 171683441
I/flutter (29275):  >>> TypewriterAnimatedText:initAnimation - 936400533
I/flutter (29275):  ^^^ _AnimatedTextKitState:build - 171683441
I/flutter (29275):  >>> TypewriterAnimatedText:animatedBuilder - 936400533
I/chatty  (29275): uid=10133(com.example.atk168) 1.ui identical 2 lines
I/flutter (29275):  >>> TypewriterAnimatedText:animatedBuilder - 936400533
I/flutter (29275):  >>> TypewriterAnimatedText:animatedBuilder - 936400533
I/chatty  (29275): uid=10133(com.example.atk168) 1.ui identical 60 lines
I/flutter (29275):  >>> TypewriterAnimatedText:animatedBuilder - 936400533
I/flutter (29275):  *** _MyHomePageState:_incrementCounter - 220007591
I/flutter (29275):  ^^^ _AnimatedTextKitState:build - 171683441
I/flutter (29275):  >>> TypewriterAnimatedText:animatedBuilder - 280798896
I/flutter (29275): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter (29275): The following NoSuchMethodError was thrown building AnimatedBuilder(animation:
I/flutter (29275): AnimationController#41b74(▶ 0.633), dirty, state: _AnimatedState#db314):
I/flutter (29275): The getter 'value' was called on null.
I/flutter (29275): Receiver: null
I/flutter (29275): Tried calling: value
I/flutter (29275): 
I/flutter (29275): The relevant error-causing widget was:
I/flutter (29275):   AnimatedBuilder file:///Users/anthony/github/awhitford/atk168/lib/main.dart:173:12
I/flutter (29275): 
I/flutter (29275): When the exception was thrown, this was the stack:
I/flutter (29275): #0      Object.noSuchMethod (dart:core-patch/object_patch.dart:54:5)
I/flutter (29275): #1      TypewriterAnimatedText.animatedBuilder (package:atk168/main.dart:121:45)
I/flutter (29275): #2      AnimatedBuilder.build (package:flutter/src/widgets/transitions.dart:1528:19)
I/flutter (29275): #3      _AnimatedState.build (package:flutter/src/widgets/transitions.dart:179:48)
I/flutter (29275): #4      StatefulElement.build (package:flutter/src/widgets/framework.dart:4825:27)
I/flutter (29275): #5      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4708:15)
I/flutter (29275): #6      StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4880:11)
I/flutter (29275): #7      BuildOwner._runWithCurrentBuildTarget (package:flutter/src/widgets/framework.dart:2708:15)
I/flutter (29275): #8      Element.rebuild (package:flutter/src/widgets/framework.dart:4407:12)
I/flutter (29275): #9      StatefulElement.update (package:flutter/src/widgets/framework.dart:4912:5)
I/flutter (29275): #10     Element.updateChild (package:flutter/src/widgets/framework.dart:3412:15)
I/flutter (29275): #11     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4733:16)
I/flutter (29275): #12     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4880:11)
I/flutter (29275): #13     BuildOwner._runWithCurrentBuildTarget (package:flutter/src/widgets/framework.dart:2708:15)
I/flutter (29275): #14     Element.rebuild (package:flutter/src/widgets/framework.dart:4407:12)
I/flutter (29275): #15     StatefulElement.update (package:flutter/src/widgets/framework.dart:4912:5)
I/flutter (29275): #16     Element.updateChild (package:flutter/src/widgets/framework.dart:3412:15)
I/flutter (29275): #17     RenderObjectElement.updateChildren (package:flutter/src/widgets/framework.dart:5727:32)
I/flutter (29275): #18     MultiChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6327:17)
I/flutter (29275): #19     Element.updateChild (package:flutter/src/widgets/framework.dart:3412:15)
I/flutter (29275): #20     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6205:14)
I/flutter (29275): #21     Element.updateChild (package:flutter/src/widgets/framework.dart:3412:15)
I/flutter (29275): #22     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4733:16)
I/flutter (29275): #23     BuildOwner._runWithCurrentBuildTarget (package:flutter/src/widgets/framework.dart:2708:15)
I/flutter (29275): #24     Element.rebuild (package:flutter/src/widgets/framework.dart:4407:12)
I/flutter (29275): #25     StatelessElement.update (package:flutter/src/widgets/framework.dart:4789:5)
I/flutter (29275): #26     Element.updateChild (package:flutter/src/widgets/framework.dart:3412:15)
I/flutter (29275): #27     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4733:16)
I/flutter (29275): #28     BuildOwner._runWithCurrentBuildTarget (package:flutter/src/widgets/framework.dart:2708:15)
I/flutter (29275): #29     Element.rebuild (package:flutter/src/widgets/framework.dart:4407:12)
I/flutter (29275): #30     ProxyElement.update (package:flutter/src/widgets/framework.dart:5066:5)
I/flutter (29275): #31     Element.updateChild (package:flutter/src/widgets/framework.dart:3412:15)
I/flutter (29275): #32     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4733:16)
I/flutter (29275): #33     BuildOwner._runWithCurrentBuildTarget (package:flutter/src/widgets/framework.dart:2708:15)
I/flutter (29275): #34     Element.rebuild (package:flutter/src/widgets/framework.dart:4407:12)
I/flutter (29275): #35     ProxyElement.update (package:flutter/src/widgets/framework.dart:5066:5)
I/flutter (29275): #36     Element.updateChild (package:flutter/src/widgets/framework.dart:3412:15)
I/flutter (29275): #37     RenderObjectElement.updateChildren (package:flutter/src/widgets/framework.dart:5727:32)
I/flutter (29275): #38     MultiChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6327:17)
I/flutter (29275): #39     Element.updateChild (package:flutter/src/widgets/framework.dart:3412:15)
I/flutter (29275): #40     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4733:16)
I/flutter (29275): #41     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4880:11)
I/flutter (29275): #42     BuildOwner._runWithCurrentBuildTarget (package:flutter/src/widgets/framework.dart:2708:15)
I/flutter (29275): #43     Element.rebuild (package:flutter/src/widgets/framework.dart:4407:12)
I/flutter (29275): #44     StatefulElement.update (package:flutter/src/widgets/framework.dart:4912:5)
I/flutter (29275): #45     Element.updateChild (package:flutter/src/widgets/framework.dart:3412:15)
I/flutter (29275): #46     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4733:16)
I/flutter (29275): #47     BuildOwner._runWithCurrentBuildTarget (package:flutter/src/widgets/framework.dart:2708:15)
I/flutter (29275): #48     Element.rebuild (package:flutter/src/widgets/framework.dart:4407:12)
I/flutter (29275): #49     ProxyElement.update (package:flutter/src/widgets/framework.dart:5066:5)
I/flutter (29275): #50     Element.updateChild (package:flutter/src/widgets/framework.dart:3412:15)
I/flutter (29275): #51     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4733:16)
I/flutter (29275): #52     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4880:11)
I/flutter (29275): #53     BuildOwner._runWithCurrentBuildTarget (package:flutter/src/widgets/framework.dart:2708:15)
I/flutter (29275): #54     Element.rebuild (package:flutter/src/widgets/framework.dart:4407:12)
I/flutter (29275): #55     StatefulElement.update (package:flutter/src/widgets/framework.dart:4912:5)
I/flutter (29275): #56     Element.updateChild (package:flutter/src/widgets/framework.dart:3412:15)
I/flutter (29275): #57     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6205:14)
I/flutter (29275): #58     Element.updateChild (package:flutter/src/widgets/framework.dart:3412:15)
I/flutter (29275): #59     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4733:16)
I/flutter (29275): #60     BuildOwner._runWithCurrentBuildTarget (package:flutter/src/widgets/framework.dart:2708:15)
I/flutter (29275): #61     Element.rebuild (package:flutter/src/widgets/framework.dart:4407:12)
I/flutter (29275): #62     StatelessElement.update (package:flutter/src/widgets/framework.dart:4789:5)
I/flutter (29275): #63     Element.updateChild (package:flutter/src/widgets/framework.dart:3412:15)
I/flutter (29275): #64     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6205:14)
I/flutter (29275): #65     Element.updateChild (package:flutter/src/widgets/framework.dart:3412:15)
I/flutter (29275): #66     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4733:16)
I/flutter (29275): #67     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4880:11)
I/flutter (29275): #68     BuildOwner._runWithCurrentBuildTarget (package:flutter/src/widgets/framework.dart:2708:15)
I/flutter (29275): #69     Element.rebuild (package:flutter/src/widgets/framework.dart:4407:12)
I/flutter (29275): #70     StatefulElement.update (package:flutter/src/widgets/framework.dart:4912:5)
I/flutter (29275): #71     Element.updateChild (package:flutter/src/widgets/framework.dart:3412:15)
I/flutter (29275): #72     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4733:16)
I/flutter (29275): #73     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4880:11)
I/flutter (29275): #74     BuildOwner._runWithCurrentBuildTarget (package:flutter/src/widgets/framework.dart:2708:15)
I/flutter (29275): #75     Element.rebuild (package:flutter/src/widgets/framework.dart:4407:12)
I/flutter (29275): #76     StatefulElement.update (package:flutter/src/widgets/framework.dart:4912:5)
I/flutter (29275): #77     Element.updateChild (package:flutter/src/widgets/framework.dart:3412:15)
I/flutter (29275): #78     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4733:16)
I/flutter (29275): #79     BuildOwner._runWithCurrentBuildTarget (package:flutter/src/widgets/framework.dart:2708:15)
I/flutter (29275): #80     Element.rebuild (package:flutter/src/widgets/framework.dart:4407:12)
I/flutter (29275): #81     ProxyElement.update (package:flutter/src/widgets/framework.dart:5066:5)
I/flutter (29275): #82     Element.updateChild (package:flutter/src/widgets/framework.dart:3412:15)
I/flutter (29275): #83     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4733:16)
I/flutter (29275): #84     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4880:11)
I/flutter (29275): #85     BuildOwner._runWithCurrentBuildTarget (package:flutter/src/widgets/framework.dart:2708:15)
I/flutter (29275): #86     Element.rebuild (package:flutter/src/widgets/framework.dart:4407:12)
I/flutter (29275): #87     StatefulElement.update (package:flutter/src/widgets/framework.dart:4912:5)
I/flutter (29275): #88     Element.updateChild (package:flutter/src/widgets/framework.dart:3412:15)
I/flutter (29275): #89     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4733:16)
I/flutter (29275): #90     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4880:11)
I/flutter (29275): #91     BuildOwner._runWithCurrentBuildTarget (package:flutter/src/widgets/framework.dart:2708:15)
I/flutter (29275): #92     Element.rebuild (package:flutter/src/widgets/framework.dart:4407:12)
I/flutter (29275): #93     BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2813:33)
I/flutter (29275): #94     WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:899:21)
I/flutter (29275): #95     RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:320:5)
I/flutter (29275): #96     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1119:15)
I/flutter (29275): #97     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1057:9)
I/flutter (29275): #98     SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:973:5)
I/flutter (29275): #102    _invoke (dart:ui/hooks.dart:157:10)
I/flutter (29275): #103    PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:253:5)
I/flutter (29275): #104    _drawFrame (dart:ui/hooks.dart:120:31)
I/flutter (29275): (elided 3 frames from dart:async)
I/flutter (29275): 
I/flutter (29275): ════════════════════════════════════════════════════════════════════════════════════════════════════
I/flutter (29275): Another exception was thrown: A RenderFlex overflowed by 99320 pixels on the bottom.
I/flutter (29275):  >>> TypewriterAnimatedText:animatedBuilder - 280798896
I/flutter (29275): Another exception was thrown: NoSuchMethodError: The getter 'value' was called on null.
I/flutter (29275):  >>> TypewriterAnimatedText:animatedBuilder - 280798896

Application finished.

具体来说,仔细看看这个:

I/flutter (29275):  >>> TypewriterAnimatedText:animatedBuilder - 936400533
I/flutter (29275):  *** _MyHomePageState:_incrementCounter - 220007591
I/flutter (29275):  ^^^ _AnimatedTextKitState:build - 171683441
I/flutter (29275):  >>> TypewriterAnimatedText:animatedBuilder - 280798896
I/flutter (29275): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter (29275): The following NoSuchMethodError was thrown building AnimatedBuilder(animation:
I/flutter (29275): AnimationController#41b74(▶ 0.633), dirty, state: _AnimatedState#db314):
I/flutter (29275): The getter 'value' was called on null.
I/flutter (29275): Receiver: null
I/flutter (29275): Tried calling: value
I/flutter (29275): 
I/flutter (29275): The relevant error-causing widget was:
I/flutter (29275):   AnimatedBuilder file:///Users/anthony/github/awhitford/atk168/lib/main.dart:173:12
I/flutter (29275): 
I/flutter (29275): When the exception was thrown, this was the stack:
I/flutter (29275): #0      Object.noSuchMethod (dart:core-patch/object_patch.dart:54:5)
I/flutter (29275): #1      TypewriterAnimatedText.animatedBuilder (package:atk168/main.dart:121:45)
I/flutter (29275): #2      AnimatedBuilder.build (package:flutter/src/widgets/transitions.dart:1528:19)
I/flutter (29275): #3      _AnimatedState.build (package:flutter/src/widgets/transitions.dart:179:48)

我只有一个TypewriterAnimatedText声明。它正在构建 TypewriterAnimatedText 936400533,已正确初始化,但单击按钮后,它开始构建280798896尚未初始化的新实例 (),因此_typewriterText为 null,调用.value该实例会触发此问题。

到底是怎么回事?我希望它build只会在之后运行initState- 但这里似乎不是这种情况?(我发现了Flutter Bug吗?)

重现这个问题有点棘手。我收到了一些来自 Windows 用户的投诉,所以他们似乎能够轻松地重现这一点。对于我自己,我只能在切换到dev频道并在 Android 模拟器上进行测试后在我的 Mac 上重现此内容。

标签: flutterflutter-animation

解决方案


推荐阅读