Flutter: Async Methods in Bloc/Cubit State Management

346 views Asked by At

While working with Cubit State Management, I have the question if the methods in the Cubit class, which access the Repository class, have to be async? The methods in the Repository class, which access the remote DB, are of course async, but why should – as far as example code shows – the methods in the Cubit class be async?

Here are the concerned code snippets:

Cubit Class:

  Future<void> getAllCost() async {

    emit(
      state.copyWith(status: ManageCostStatus.loading),
    );


    try {
      late List<Cost> costs = [];
      costs = await supabaseRepsitory.getAllCost();


      emit(state.copyWith(
        status: ManageCostStatus.success,
        costs: costs,
      ));


    } on Exception {
      emit(state.copyWith(status: ManageCostStatus.error));
    }
  }

Repository Class

Future<List<Cost>> getAllCost() async {
    final dataCost = await supabaseInstance
        .from('notes')
        .select<List<Map<String, dynamic>>>(); 

    List<Cost> costList = List<Cost>.from(
        dataCost.map((e) => Cost.fromMap(e))); 

    return costList;
  }

To be honest, I would like to make the Cubit methods sync, as sync methods and variables are more easy to handle in the Screen classes.

2

There are 2 answers

0
Tomiwa Idowu On BEST ANSWER

The getAllCost() function in your cubit class need to be mark as async because the function call supabaseRepsitory.getAllCost(); which is a future that needs to be awaited, anytime you call a future function you must await the function and mark your function as async

What's a future in dart?: A future represents the result of an asynchronous operation

What is an asynchronous operation?: Asynchronous operations let your program complete work while waiting for another operation to finish.

Here are some common asynchronous operations:

  • Fetching data over a network.
  • Writing to a database.
  • Reading data from a file.

Such asynchronous computations usually provide their result as a Future or, if the result has multiple parts, as a Stream.

you can read more about async and await here: https://dart.dev/codelabs/async-await

Future<void> getAllCost() async {

    emit(
      state.copyWith(status: ManageCostStatus.loading),
    );


    try {
      late List<Cost> costs = [];
      costs = await supabaseRepsitory.getAllCost();


      emit(state.copyWith(
        status: ManageCostStatus.success,
        costs: costs,
      ));


    } on Exception {
      emit(state.copyWith(status: ManageCostStatus.error));
    }
  }
0
Tomasz Rejdych On

It has to be async because you call async code. It's normal and fine. If you really want to avoid async method in a cubit you can:

void getAllCost() {
  emit(
    state.copyWith(status: ManageCostStatus.loading),
  );

  supabaseRepsitory.getAllCost().then((costs) {
    emit(
      state.copyWith(
        status: ManageCostStatus.success,
        costs: costs,
      ),
    );
  }).onError((e, s) {
    emit(state.copyWith(status: ManageCostStatus.error));
  });
}