Flutter Bad State No Element

Viewed 17433

I am trying to delete my data from a database, and proceed to navigate to my homepage if it succeeds.

Below are my code:

StatelessWidget that consist of deleteFromDatabase method which passed an Id(String), an a 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 method called from StatelessWidget and shows an AlertDialog to confirm deletion:

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'),
      ),
    ],
  ),
 );
}

deleteFromList method From My Provider class:

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 from Provider Class:

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

Note: I am able to delete my data successfully from my database, however right before it navigates to my HomePage, an error pops out for a split second as a form of Red Screen: Bad State: No Element

Below are the full error message from my Log:

The following StateError was thrown building Consumer(dirty, dependencies: [_InheritedProviderScope, _InheritedTheme, _LocalizationsScope-[GlobalKey#5ce12]]): Bad state: No element

The relevant error-causing widget was:

Consumer<SettingsProvider>

When the exception was thrown, this was the stack:

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

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

#2 PreviewExercisePage.build.<anonymous closure> (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)

3 Answers

This is happens when the list is empty or maybe the first element is empty, so you should check the list is not empty.

List list = [];

print(list[0])

is sure you'll receive like this message:

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)

the solution is:

List list = [];

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

I hope this is helpful for someone Thanks!

As previously mentioned in the comments, it's likely that checking the values of an empty List causes the error. A workaround for this is to have a checker if the List is empty on both CustomExercise findById(String) and deleteFromList(String).

i.e.

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

We were using Drift (formerly Moor) and its watchSingle() method. That will throw this error, if no matching database row is found.

It was very hard to track down since a stream was emitting the error and it had no stack trace attached to it.

The fix was to use watch() with limit(1) instead and skip processing if the result is empty.

Related