flutterdartflutter-blocflutter-cubit

How to use BlocBuilder inside ReorderableListView?


When I try to use BlocBuilder inside ReorderableListView i get an Could not find the correct Provider<ThemeCubit> above this BlocBuilder<ThemeCubit, ThemeState> Widget error. The error occurs when I drag an item inside list.

Example:

List<int> _items = List<int>.generate(50, (int index) => index);

ReorderableListView(
      children: <Widget>[
        for (int index = 0; index < _items.length; index += 1)
          Container(
            key: Key(index.toString()),
            child: BlocBuilder<ThemeCubit, ThemeState>(
              builder: (___, ____) {
                return Text('Item ${_items[index]}');
              }
            )
          )
      ],
      onReorder: (int oldIndex, int newIndex) {},
    )

Weirdly enough, if I try to access the bloc data with context.read<ThemeCubit>() I don't get an error.


Reproducible example (main.dart)

Problem is reproduced when you drag an item in list.

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

class SimpleCubit extends Cubit<int>
{
  SimpleCubit() : super(0);
}

void main() async {
  runApp(MyTrip());
}

class AppName extends StatelessWidget {
  AppName({super.key});

  final List<int> _items = List<int>.generate(50, (int index) => index);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: MultiBlocProvider(
          providers: [
            BlocProvider<SimpleCubit>(
              create: (_) => SimpleCubit()
            ),
          ],
          child: ReorderableListView(
            children: <Widget>[
              for (int index = 0; index < _items.length; index += 1)
                Container(
                  key: Key(index.toString()),
                  child: BlocBuilder<SimpleCubit, int>(
                    builder: (_, state) {
                      return Text(state.toString());
                    }
                  )
                )
            ],
            onReorder: (int oldIndex, int newIndex) {},
          ),
        ),
      )
    );
  }
}

Solution

  • Just wrap your MaterialApp with the BlocProvider, your error indicates that it does not find the context, since you only provide it to the ReorderableListView widget, so you better create your bloc globally so that any widget with context can call it that way: (BUT IT HAS TO BE IN YOUR MAIN MATERIAL APP in MyTrip())

    void main() async {
      runApp(MyTrip());
    }
    
    class MyTrip extends StatelessWidget {
    
     MyTrip({super.key});
        
     @override
      Widget build(BuildContext context) {
        return MultiBlocProvider( //  like this
          providers: [
            BlocProvider<SimpleCubit>(create: (_) => SimpleCubit()),
          ],
          child: MaterialApp(
            [...] // here it has to be your routes, theme, translation, etc...
          ),
        );
      }