Flutter Bad State 无元素

Posted

技术标签:

【中文标题】Flutter Bad State 无元素【英文标题】:Flutter Bad State No Element 【发布时间】:2020-10-17 16:08:07 【问题描述】:

我正在尝试从数据库中删除我的数据,如果成功则继续导航到我的主页。

下面是我的代码:

StatelessWidget 由 deleteFromDatabase 方法组成,该方法传递了一个 Id(String)、一个 context

Consumer<SettingsProvider>(
      builder: (context, settingsProvider, child) 
        final exerciseSettings = settingsProvider.findById(id);
        if (exerciseSettings == null) 
          return Center(
            child: CircularProgressIndicator(),
          );
        
        return PreviewExerciseItem(
          exerciseSettings: exerciseSettings,
          id: id,
          navigateToEdit: () =>
              _navigateToEditPage(exerciseSettings, context),
          deleteFromDatabase: () => _deleteFromDatabase(id, context),
          navigateToCountDown: () =>
              navigateToCountDownPage(exerciseSettings, context),
        );
      ,
    ),

_deleteFromDatabase 方法从 StatelessWidget 调用并显示一个 AlertDialog 以确认删除:

void _deleteFromDatabase(String id, context) async 
await showDialog(
  context: context,
  builder: (context) => new AlertDialog(
    title: new Text("Are you sure you want to delete?"),
    actions: <Widget>[
      new FlatButton(
        onPressed: () => Navigator.of(context).pop(false),
        child: new Text('No'),
      ),
      new FlatButton(
        onPressed: () async 
          try 
            Navigator.of(context).pop(true);
            await Provider.of<SettingsProvider>(context, listen: false)
                .deleteFromList(id);
            Navigator
                .pushNamedAndRemoveUntil(context,HomePage.routeName, (Route route) => route.isFirst);
           catch (e) 
            print(e);
          
        ,
        child: new Text('Yes'),
      ),
    ],
  ),
 );

从我的 Provider 类中的 deleteFromList 方法:

Future<void> deleteFromList(String id) async
try
  final _itemIndex = _items.indexWhere((item) => item.id == id);
  await _databaseHelper.deleteExercises(id);
  _items.removeAt(_itemIndex);
  notifyListeners();
catch(e)
  print(e);
 

来自提供者类的findById:

CustomExercise findById(String id) 
  return _items.firstWhere((prod) => prod.id == id);

注意:我可以从我的数据库中成功删除我的数据,但是在它导航到我的主页之前,会在瞬间弹出一个错误,形式为 Red Screen: Bad State: No Element

以下是我的日志中的完整错误消息:

在构建 Consumer(dirty, dependencies: [_InheritedProviderScope, _InheritedTheme, _LocalizationsScope-[GlobalKey#5ce12]]) 时引发了以下 StateError: 不良状态:无元素

相关的导致错误的小部件是:

Consumer<SettingsProvider>

当异常被抛出时,这是堆栈:

#0 ListMixin.firstWhere (dart:collection/list.dart:150:5)

#1 SettingsProvider.findById (package:workoutapp/providers/settings_provider.dart:12:19)

#2 PreviewExercisePage.build.&lt;anonymous closure&gt; (package:workoutapp/pages/preview_exercise_page.dart:68:55)

#3 Consumer.buildWithChild (package:provider/src/consumer.dart:175:19)

#4 SingleChildStatelessWidget.build (package:nested/nested.dart:260:41)

【问题讨论】:

Bad State: No Element 主要发生在您调用空列表的方法并需要通过其元素检查值时(在本例中为 settingsProvider.findById(id) 时调用 firstWhere in一些列表),您可以发布该方法 findById 的代码吗? 嗨,是的,你是对的。显然因为我使用消费者,它一直在监听变化,因此在我删除数据后,它收到一个空值,据说它应该已经停止监听。因此,我已经通过使用 Provider.of(context,listen: false) 而不是 Consumer 来解决我的问题,以确保它只在屏幕加载时收听一次 另外补充一点,就我而言,在导航到我的主页之前,该错误仅在我的屏幕上出现一瞬间,并且数据确实已成功从数据库中删除。所以就我而言,问题不在于 findById 函数。但是感谢之前我忽略了该功能并一直认为我的问题在于删除功能。 同样的问题...请帮助...***.com/questions/64154373/… 【参考方案1】:

当列表为空或第一个元素为空时会发生这种情况,因此您应该检查列表是否为空。

List list = [];

print(list[0])

您肯定会收到这样的消息:

Unhandled exception:
Bad state: No element
#0      List.first (dart:core-patch/growable_array.dart:332:5)
#1      main (file:///C:/Users/onbody/androidStudioProjects/nmae/bin/name.dart:9:14)
#2      _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:281:32)
#3      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)

解决办法是:

List list = [];

if (list.isNotEmpty) 
    print(list[0]);
   else 
    print('the list is empty'!);
  

我希望这对某人有帮助谢谢!

【讨论】:

【参考方案2】:

正如前面在 cmets 中提到的,检查空 List 的值很可能会导致错误。如果CustomExercise findById(String)deleteFromList(String) 上的列表都为空,则有一个解决方法。

if(_items != null && _items.length > 0)

【讨论】:

【参考方案3】:

我们使用的是 Drift(以前的 Moor) 及其watchSingle() 方法。如果找不到匹配的数据库行,则会抛出此错误。

很难追踪,因为一个流正在发出错误并且它没有附加堆栈跟踪。

解决方法是使用 watch()limit(1),如果结果为空则跳过处理。

【讨论】:

以上是关于Flutter Bad State 无元素的主要内容,如果未能解决你的问题,请参考以下文章

Flutter - Stateful(有状态) 和 stateless(无状态) widgets

Flutter 组件的生命周期State 管理及局部重绘 | 开发者说·DTalk

Flutter 组件的生命周期State 管理及局部重绘 | 开发者说·DTalk

Flutter UI 渲染原理概览

Flutter UI 渲染原理概览

Flutter漫说:组件生命周期State状态管理及局部重绘的实现(Inherit)