skip to Main Content

I am working on the application and emitting the states for particular cubit in the main file in the "MultiBlocProvider" like this.

return MultiBlocProvider(
      providers: [
        BlocProvider<Cubit1>(
          create: (context) {
            Cubit1 cubit = Cubit1(Cubit1State());
            cubit.fetchData1FromApi();
            return cubit;
          },
        ),
        BlocProvider<Cubit2>(
          create: (context) {
            Cubit2 cubit = Cubit2(Cubit2State());
            cubit.fetchData2FromApi();
            return cubit;
          },
        ),
]

and in my cubit, I declared these functions like this.

 fetchData1FromApi() async {
    final data = await _state.api.retrieveData(0,maxValue);
    emit(DataState(data));
  }

Now, purpose of this code is that whenever application starts, it first fetch data in the main file so that we can use that data and do not need to use FutureBuilder. However, I am not getting the state when application starts. I wrote same code for HydratedBloc and it is working. I think, it should also work. Any clue? Thanks:)

3

Answers


  1. Chosen as BEST ANSWER

    The main issue is that when we fetch api data within main file, it takes time to fetch the data. Before that operation is completed, it shows the first page/screen of application. As, I am retrieving data from private API and database and not using firebase, there I need cache if I want to retrieve data in the main file and if I do not want to use FutureBuilders because of too many states. Simple solution is to use HydratedCubit because then api is called through it and it always have some data stored. HydratedCubit uses Hive but you can also create your DB using Hive, if you do not want to use Hydrated Cubit and then can use simple Cubit. I am writing simple HydratedCubit below:

    class Cubit1 extends HydratedCubit<Cubit1ApiState> {
      Cubit1(Cubit1ApiState state) : super(state);
    
      fetchData() async {
        final data = await _state.api.retrieveData(0, maxValue);
        emit(Data1State(data));
      }
    
      @override
      Data1ApiState? fromJson(Map<String, dynamic> json) {
        try {
          final state = Data1State(DataType.fromJson(json));
          return state;
        } catch (_) {
          return null;
        }
      }
    
      @override
      Map<String, dynamic>? toJson(Data1ApiState state) {
        if (state is Data1State) {
          return state.data.toJson();
        } else {
          return null;
        }
      }
    }
    
    abstract class Data1ApiState extends Equatable {}
    
    class Data1InitialState extends Data1ApiState {
      @override
      List<Object?> get props => [];
    }
    
    class Data1State extends Data1InitialState {
      Data1State(this.data);
      final DataType data;
    
      @override
      List<Object?> get props => [data];
    }
    

    Now, you can fetch data in the main MultiBlocProvider like this.

    return MultiBlocProvider(
          providers: [
            BlocProvider<Cubit1>(
              create: (context) {
                Cubit1 cubit = Cubit1(Data1InitialState());
                cubit.fetchData();
                return cubit;
              },
          ),
    ]
    

  2. I think if you use bloc in the correct way, your problem maybe solve.
    you should use Event for eh bloc for fetch Api or other work

    Scaffold(
           appBar: getAppBarWidget('appBar', []),
          body: MultiBlocProvider(providers: [
            BlocProvider(create: (context) => FinishBloc()..add(InitialFinishEvent())),
            BlocProvider(create: (context) => SendTourInfoCubit(),
          ], child: const BodyContent()),
        );
      }
    
    Login or Signup to reply.
  3. If the cubits/blocs are not used (e.g. by a BlocBuilder or BlocListener that has been called in a Widget for those cubits/blocs), the cubits/blocs are never created. I.e. the create callback is never run. Check that first.

    There is a property on the BlocProvider, lazy:, that can be set to false. This determines whether the bloc/cubit should be created lazily. Defaults to true. You can change this to false, making sure that the cubits/blocs are created by the BlocProvider right away.

    For simplicity, I’d also use the cascade notation to streamline the create calls as follows:

    BlocProvider<Cubit1>(
       create: (context) => Cubit1(Cubit1State())..fetchData1FromApi()
    ),
    BlocProvider<Cubit2>(
       create: (context) => Cubit2(Cubit2State())..fetchData2FromApi()
    )
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search