FlutterError(在dispose()之后调用setState():(生命周期状态:已失效,未安装) [英] FlutterError (setState() called after dispose(): (lifecycle state: defunct, not mounted)

查看:207
本文介绍了FlutterError(在dispose()之后调用setState():(生命周期状态:已失效,未安装)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

错误在两个区域引发(并且应用程序冻结(当应用程序最小化,单击电话返回按钮时,或者在flutter应用程序顶部运行另一个应用程序时。Flutter版本:1.20.2(先前版本没有这个问题):这两个函数是:

the error is thrown in two areas (and the app freezes (when the app is minimized, when phones back button is clicked, or when another app runs on top of the flutter app. Flutter version: 1.20.2 (previous versions did not have this issue): The two functions are:

@override
void initState() {
super.initState();
getItems();
} 

getItems() async {
 initClearVisibility();
 initFilters();
 setState(() {
 loadingItems = true;
 Visibility(visible: true, child: CircularProgressIndicator());
 });

QuerySnapshot querySnapshot = await query.get();
 items = querySnapshot.docs;
 lastDocument = querySnapshot.docs[querySnapshot.docs.length - 1];
 setState(() {
 loadingItems = false;
 Visibility(visible: false, child: CircularProgressIndicator());
 });
}

initClearVisibility() {
 if (Str.filterSelectCategory != Str.CATEGORY) {
  clearCategoryVisible = true;
  allCategoriesVisible = false;
   categoryValue = Str.filterSelectCategory;
  setState(() {});
 }
}

initFilters() async {   
 filterDefaultItems();
}

filterDefaultItems() async {
  query = _firestore
  .collection(Str.ITEMS)
  .where(Str.IS_ITEM_SOLD, isEqualTo: false) 
  .where(Str.ADDRESS, isEqualTo: userAddress1)
  //.orderBy(Str.DATE_POSTED)
  .limit(perPage);
}

第二个区域也位于以下代码中,我也得到了::

Second area is on the following code where I am also getting: :

class FABBottomAppBarItem {
FABBottomAppBarItem({this.iconData, this.itemColor}); //, this.text});
IconData iconData;
var itemColor;
//String text;
}

class FABBottomAppBar extends StatefulWidget {
 FABBottomAppBar({
 this.items,
 this.centerItemText,
 this.height: 65.0,
 this.iconSize: 24.0,
 this.backgroundColor,
 this.color,
 this.selectedColor,
 this.notchedShape,
 this.onTabSelected,
 }) {
 assert(this.items.length == 2 || this.items.length == 4);
}
final List<FABBottomAppBarItem> items;
final String centerItemText;
final double height;
final double iconSize;
final Color backgroundColor;
final Color color;
final Color selectedColor;
final NotchedShape notchedShape;
final ValueChanged<int> onTabSelected;

@override
State<StatefulWidget> createState() => FABBottomAppBarState();
}

class FABBottomAppBarState extends State<FABBottomAppBar> {
//int _selectedIndex = 0;
int unreadCount = 0;

_updateIndex(int index) {
 widget.onTabSelected(index);
 setState(() {
  //_selectedIndex = index;
  });
}

@override
void initState() {
 super.initState();
 countDocuments();
}

@override
Widget build(BuildContext context) {
List<Widget> items = List.generate(widget.items.length, (int index) {
  return _buildTabItem(
    item: widget.items[index],
    index: index,
    onPressed: _updateIndex,
  );
});
items.insert(items.length >> 1, _buildMiddleTabItem());

return BottomAppBar(
  shape: widget.notchedShape,
  child: Row(
    mainAxisSize: MainAxisSize.max,
    mainAxisAlignment: MainAxisAlignment.spaceAround,
    children: items,
  ),
  color: widget.backgroundColor,
 );
}

Widget _buildMiddleTabItem() {
 return Expanded(
  child: SizedBox(
    height: MediaQuery.of(context).size.height * 0.075, //widget.height,
    child: Column(
      mainAxisSize: MainAxisSize.min,
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        SizedBox(
          height: MediaQuery.of(context).size.height * 0.04,
        ), 
        Text(
          widget.centerItemText ?? '',
          style: TextStyle(
              color: BwerereTheme.bwerereRed,
              fontSize: 14.0,
              fontWeight: FontWeight.w900),
        ),
      ],
    ),
  ),
  );
}

Widget _buildTabItem({
 FABBottomAppBarItem item,
 int index,
 ValueChanged<int> onPressed,
 }) 
{
 return Expanded(
  child: SizedBox(
    height: MediaQuery.of(context).size.height * 0.065,
    child: Material(
      type: MaterialType.transparency,
      child: InkWell(
        onTap: () => onPressed(index),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Stack(
              children: <Widget>[
                Icon(item.iconData,
                    color: item.itemColor,
                    size: IconTheme.of(context).size * 1.2),
                index == 2 ? badge() : Container()
              ],
            )
          ],
        ),
      ),
    ),
   ),
   );
  }

  Widget badge() => unreadCount < 1
   ? Container()
    : Container(
      padding: EdgeInsets.all(4.0),
      decoration: BoxDecoration(
          color: BwerereTheme.bwerereRed, shape: BoxShape.circle),
      child: Center(
        child: RobotoFont(
            text: "$unreadCount",
            textSize: 12.0,
            textColor: Colors.white,
            fontWeight: FontWeight.w400),
      ));

 void countDocuments() async {
 final uid = await FetchUserData().getCurrentUserID();
 QuerySnapshot _myDoc = await FirebaseFirestore.instance
    .collection("userUnreadMessages")
    .doc(uid)
    .collection(Str.MESSAGE_COLLECTION)
    .get();
 List<DocumentSnapshot> _myDocCount = _myDoc.docs;
 setState(() {
  unreadCount = _myDocCount.length;
  print('NOTIY LENGTH::: $unreadCount');
 });
}

}

FABBottomAppBarState的FRAMEWORK.DART错误

THE ERROR FROM FRAMEWORK.DART for FABBottomAppBarState.

在HomePage()的getItems上引发了相同的错误

The same error thrown on the getItems on HomePage()


发生了异常。
FlutterError(在dispose()之后调用setState():FABBottomAppBarState#250ac(生命周期状态:已关闭,未安装)
如果您在不再需要其状态的小部件的State对象上调用setState(),则会发生此错误出现在窗口小部件树中(例如,其父窗口小部件不再在其内部包含窗口小部件)。当代码从计时器或动画回调调用setState()时,可能会发生此错误。
此计时器可能会导致计时器计时或停止在dispose()回调中收听动画;另一种解决方法是在调用setState()之前检查此对象的 mount属性,以确保该对象仍在树中。如果正在调用setState(),则表示发生内存泄漏,因为从树中删除了另一个State对象后,该对象仍保留对该State对象的引用。为避免内存泄漏,请考虑在dispose()期间中断对此对象的引用。)

Exception has occurred. FlutterError (setState() called after dispose(): FABBottomAppBarState#250ac(lifecycle state: defunct, not mounted) 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. 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().)

随后的进一步调查显示该应用程序占用了手机约400MB的内存(Ram),我觉得这太高了。

Further investigation then shows that the app takes about 400MB of memory (Ram) for the phone which I find rather too high.

帮助弄清楚问题的实际帮助。

Help on figuring out the issue will really help. Thanks in advance.

其他信息:
在android 7.0上运行时,发生错误1.20.2。请参见 https://github.com/flutter/flutter/issues/35900 。请注意,我已升级到Flutter 1.20.2 adnd降级到1.7.5将需要在升级后特别是在Firestore上进行很多更改(注意: https://firebase.flutter.dev/docs/migration (最近更新)。

Additional information: Error occurs when running on android 7.0, flutter 1.20.2. See similar/related issue on https://github.com/flutter/flutter/issues/35900. Note that I upgraded to Flutter 1.20.2 adnd Downgrading to 1.7.5 will require a lot of changes I made after upgrading especially on Firestore (NOTE: https://firebase.flutter.dev/docs/migration which was recently updated).

推荐答案

等待 之后,您的窗口小部件可能不再挂载。那时执行setState会给您一个例外。这实际上是一件好事,因为您在其他地方,因此后面的代码无论如何也不应执行。

After an await, your widget may not be mounted anymore. Doing setState gives you an exception at that time. This is actually a good thing, the code that follows should not be executing anyway, since you are somewhere else.

对于dispose()之后调用的 setState(),您有三种选择"例外:

You have three options about the "setState() called after dispose()" exception:


  1. 安全地忽略它。

  2. if(!mount)返回处放置一个;在每个之间放置一个等待和 setState()。每次等待之后,将其放置是一个好习惯。

  3. 替换您的 setState()使用 setStateIfMounted()进行调用并将其定义为:

  1. Safely ignore it. The exception is saving your function from continuing.
  2. Place a if (!mounted) return; between each await and setState(). It may be a good habit to put it after each await.
  3. Replace your setState() calls with setStateIfMounted() and define it as:


void setStateIfMounted(f) {
  if (mounted) setState(f);
}

我在视频

这篇关于FlutterError(在dispose()之后调用setState():(生命周期状态:已失效,未安装)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆