Flutter错误(在dispose()后调用setState():(生命周期状态:失效,未安装)

s5a0g9ez  于 2023-02-16  发布在  Flutter
关注(0)|答案(6)|浏览(105)

错误在两个区域抛出(和应用程序冻结(当应用程序最小化时,当点击手机后退按钮时,或当另一个应用程序在flutter应用程序上运行时。Flutter版本:1.20.2(以前的版本没有此问题):这两项职能是:

@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);
}

第二个方面是在下面的代码,我也得到::

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的框架. DART错误。
在HomePage()上的getItems上抛出相同的错误
出现异常,在dispose()后调用FlutterError(setState()):FABBottomAppBarState#250ac(生命周期状态:defunct,not mounted)如果您调用状态对象上的setState(),则会发生此错误,该对象用于不再出现在小部件树中的小部件(例如,其父小部件在其构建中不再包含该小部件)。当代码从计时器或动画回调调用setState()时,可能会发生此错误。首选解决方案是取消计时器或停止侦听dispose()回调中的动画。另一个解决方案是在调用setState()之前检查此对象的"mounted"属性,以确保该对象仍在树中。如果调用setState(),则此错误可能指示内存泄漏,因为在从树中删除此State对象后,另一个对象仍保留对此对象的引用。为避免内存泄漏,请考虑在dispose()期间中断对此对象的引用。)
进一步的调查显示,该应用程序需要约400MB的内存(RAM)的手机,我觉得相当太高。
帮助解决这个问题真的会很有帮助。提前感谢。
补充信息:在android 7.0 flutter 1.20.2上运行时出现错误。请参见https://github.com/flutter/flutter/issues/35900上的类似/相关问题。请注意,我升级到了flutter 1.20.2,并且升级到1.7.5后需要进行大量更改,尤其是在Firestore上(注意:最近更新的https://firebase.flutter.dev/docs/migration)。

bqujaahr

bqujaahr1#

await之后,你的小部件可能不再被挂载。执行setState会在那时给你一个异常。这实际上是一件好事,下面的代码无论如何都不应该执行,因为你在别的地方。
关于“在dispose()之后调用setState()”异常,您有三种选择:
1.安全地忽略它。异常是保存您的异步函数从继续。您将看到一个异常在您的日志中,您可以忽略。
1.在每个awaitsetState()之间放置一个if (!mounted) return;。把它放在每个await之后可能是一个好习惯。如果你对它过敏,这也会停止异步函数并隐藏异常。
1.将setState()调用替换为setStateIfMounted(),并将其定义为:

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

但是,if (mounted) setState()并不停止异步函数,因此第三个选项是here所讨论的三个选项中最差的。
我还将在本video中解释这些方法。

r3i60tvu

r3i60tvu2#

您可以使用:

if (this.mounted) { // check whether the state object is in tree
    setState(() {
      // make changes here
    });
  }

mounted检查此对象当前是否在tree. mounted class

v8wbuo2f

v8wbuo2f3#

对于初学者和容易理解的检查bool isMount = true;时,dispose()将被称为bool isMount = false;setState()不会被调用。

class TotalBooks extends StatefulWidget {
  TotalBooks({Key? key}) : super(key: key);
  // code omitted..
  bool isMount = true;
  @override
  _TotalBooksState createState() => _TotalBooksState();
}

class _TotalBooksState extends State<TotalBooks> {
  @override
  void initState() {
  // code omitted..
      if (widget.isMount) {
        setState(() {
  // code omitted..
        });
      }
    });
    super.initState();
  }

  @override
  void dispose() {
    // TODO: implement dispose
    widget.isMount = false;
  // code omitted..        super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return SizedBox();
  }
}
6rvt4ljy

6rvt4ljy4#

@override
void setState(VoidCallback fn) {
  if (!mounted) return;
  super.setState(fn);
}
ykejflvf

ykejflvf5#

我发现没有那么完美和简单的方法!我写了一个子类扩展State,你可以用VMState代替State,然后只调用safeSetState代替setState

import 'package:flutter/widgets.dart';

class VMState<T extends StatefulWidget> extends State<T> {

  bool didDispose = false;

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    throw UnimplementedError();
  }

  @override
  void dispose() {
    didDispose = true;
    super.dispose();
  }

  void safeSetState(VoidCallback callback) {
    if (!didDispose) {
      setState(callback);
    }
  }
  
}

有人说使用mounted,但这带来了另一个例外。

gojuced7

gojuced76#

有了这个代码,我的错误已经解决了!

if (mounted) { 
setState(() {
  // make your changes here
});
}

相关问题