在StatelessWidget中使用StatefulBuilder时使用dispose()

时间:2018-11-11 11:24:58

标签: dart flutter

我正在使用StatefulBuilder小部件来更新我的值,并且一切正常。

StatefulBuilder(
      builder: (BuildContext context, StateSetter setState) {
   return Mywidget();
});

由于此小部件位于“选项卡”视图中,因此当我滚动到下一个选项卡时,会在控制台中收到以下异常。

E/flutter ( 7147): [ERROR:flutter/shell/common/shell.cc(188)] Dart Error: Unhandled exception:
E/flutter ( 7147): setState() called after dispose(): _StatefulBuilderState#09a22(lifecycle state: defunct, not mounted)
E/flutter ( 7147): This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback. The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree.
E/flutter ( 7147): This error might indicate a memory leak if setState() is being called because another object is retaining a reference to this State object after it has been removed from the tree. To avoid memory leaks, consider breaking the reference to this object during dispose().
E/flutter ( 7147): #0      State.setState.<anonymous closure> (package:flutter/src/widgets/framework.dart:1097:9)
E/flutter ( 7147): #1      State.setState (package:flutter/src/widgets/framework.dart:1123:6)
E/flutter ( 7147): #2      ImageItem.actionColumn.<anonymous closure>.<anonymous closure> (package:silkthread/widgets/image_item.dart:197:19)
E/flutter ( 7147): #3      _RootZone.runUnary (dart:async/zone.dart:1379:54)
E/flutter ( 7147): #4      _FutureListener.handleValue (dart:async/future_impl.dart:129:18)
E/flutter ( 7147): #5      Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:642:45)
E/flutter ( 7147): #6      Future._propagateToListeners (dart:async/future_impl.dart:671:32)
E/flutter ( 7147): #7      Future._complete (dart:async/future_impl.dart:476:7)
E/flutter ( 7147): #8      _SyncCompleter.complete (dart:async/future_impl.dart:51:12)
E/flutter ( 7147): #9      _RootZone.runUnary (dart:async/zone.dart:1379:54)
E/flutter ( 7147): #10     _FutureListener.handleValue (dart:async/future_impl.dart:129:18)
E/flutter ( 7147): #11     Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:642:45)
E/flutter ( 7147): #12     Future._propagateToListeners (dart:async/future_impl.dart:671:32)
E/flutter ( 7147): #13     Future._complete (dart:async/future_impl.dart:476:7)
E/flutter ( 7147): #14     _SyncCompleter.complete (dart:async/future_impl.dart:51:12)
E/flutter ( 7147): #15     _AsyncAwaitCompleter.complete.<anonymous closure> (dart:async/runtime/libasync_patch.dart:33:20)
E/flutter ( 7147): #16     _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
E/flutter ( 7147): #17     _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)

由于具有StatefulBuilder小部件的页面是StatelessWidget,所以无法调用dispose()方法。

那么在使用StatefulBuilder时如何避免这种异常?

编辑: 我正在尝试与文章https://medium.com/flutter-community/stateful-widgets-be-gone-stateful-builder-a67f139725a0中提到的内容相同。

class ImageItem extends StatelessWidget {
  @override
  Widget build(BuildContext context) {

      return StatefulBuilder(
           builder: (BuildContext context, StateSetter setState) {
               setState(() {
                 likesCount = post.likesCount;
               });

              return ActionChip(label: Text(likesCount);
      });
  }
}

2 个答案:

答案 0 :(得分:1)

创建并实现自己的StatefulBuilder,添加dispose方法,如下所示:

import 'package:flutter/material.dart';

typedef Disposer = void Function();

class MyStatefulBuilder extends StatefulWidget {
  const MyStatefulBuilder({
    Key key,
    @required this.builder,
    @required this.dispose,
  }) : assert(builder != null),
        super(key: key);

  final StatefulWidgetBuilder builder;
  final Disposer dispose;

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

class _MyStatefulBuilderState extends State<MyStatefulBuilder> {
  @override
  Widget build(BuildContext context) => widget.builder(context, setState);

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

像这样使用它:

return AlertDialog(
        title: Text('Hello, world.'),
        content: MyStatefulBuilder(
          dispose: () {
            print('dispose!!!!!!!!!!!!');
          },
          builder: (BuildContext context, StateSetter setState) {
            return Container();
          }
    )
);

答案 1 :(得分:0)

包装您的代码

if(mounted) {
  setState(() { ... });
}

避免在未安装小部件时调用setState()