Dart/Flutter: how to use return of one method in another method? both invoked in the Class Constructor

Asked

Viewed 836 times

0

I am using Dart/Flutter to develop an application and in it I have two Firebase Listeners methods, as shown below, and I would like to know how, in the constructor method, I trigger one of the methods only after the first one has already populated the necessary variables.

Class and its builder:

class ItineraryBloc extends ChangeNotifier {
  ItineraryBloc() {
    // aqui irão as chamadas dos métodos citados acima...
  }


  List<Localidade> _listLocales = [];
  List<Veiculo> _listVehicles = [];
  String _selectedLocaleId = '';

...

1st method:

    // LISTENER DAS LOCALIDADES CADASTRADAS
  Future<List<Localidade>> getListAllLocales() async {
    _db.collection('localidades').orderBy('nome').snapshots().listen((snapshot) {
      listLocales = snapshot.docs.map((e) => Localidade.fromDocument(e)).toList();
      selectedLocaleId = listLocales.firstWhere((item) => item.sedeRegional == true).id;
      notifyListeners();
    });
    return listLocales;
  }

2° method:

// LISTENER DOS VEÍCULOS CADASTRADOS POR LOCALIDADES
  Future<List<Veiculo>> getListAllVehiclesByLocale() async {
    _db.collection('veiculos').where('idLocalidade', isEqualTo: selectedLocaleId).orderBy('placa').snapshots().listen((qSnap) {
      if (qSnap.docs.isNotEmpty) {
        listVehicles = qSnap.docs.map((v) => Veiculo.fromDocument(v)).toList();
        selectedVehicle = listVehicles[0];
      } else {
        listVehicles = [];
      }

      notifyListeners();
    });
    return listVehicles;
  }
}

The method getListAllVehiclesByLocale depends on the variable selectedLocaleId which is set in the method getListAllLocales.

My idea is to call these two methods in the class builder to populate the lists and related variables so only then do I use them in a widget. However, the widget needs to display a loading/processing feedback of these list to then display them in their respective PagesView and ListView.

1 answer

0

and would like to know how, in the constructor method, I trigger one of the methods only after the first one has already populated the necessary variables.

In Dart, there is the keyword await.

This command is used to wait for the end of an asynchronous function to only then proceed with what depends on it, without blocking the execution of your program.

Without it, you’d need to create callbacks between your Futures, only this makes it difficult to read code and gets more confused (less linear). It would be something like:

getListAllLocales().then((retornoDaPrimeiraFuncao) => getListAllVehiclesByLocale());

Its functions already return as one Future. If you want to learn more about asynchrony and Future/Await, there is this great codelab teaching the concepts (in English).

So to use the await that is recommended by language, simply put the await before the function call:

await getListAllLocales();
await getListAllVehiclesByLocale();

You can’t use it await in a function that is not marked as asynchronous (async), and you cannot mark a constructor as asynchronous. So a solution is to create an asynchronous method and in the constructor call it without await:

Future futuroASerMonitorado;
ItineraryBloc() {
    futuroASerMonitorado= FuncaoAssincrona();
  }
void FuncaoAssincrona ()async{
    await getListAllLocales();
    await getListAllVehiclesByLocale();
  }

However, the widget needs to display a loading/processing feedback of these list to then display them on their respective Pagesview and Listview.

A perfect widget for this case is the Futurebuilder. You provide a Future to it, and it builds itself based on the state of that Future. In your case, a simple example would be:

return FutureBuilder(
    future: futuroASerMonitorado,
    builder: (BuildContext context, AsyncSnapshot snapshot) {   
      if(snapshot.connectionState == ConnectionState.waiting){
          return  Center(child: Text('Carregando...'));
      }else{
          if (snapshot.hasError)
            return Center(child: Text('Erro: ${snapshot.error}'));
          else
            return ListView(); //Aqui você tem a certeza que o Futuro completou e pode acessar o retorno dele com snapshot.data
      }
    },
  );
  • Even implementing your suggestions, @Naslausky, the return is still incorrect (see image: http://prntscr.com/v2hwgd ). Because, return the empty variables when loaded the Class. Should be set, since prints occur after the "awaits" of the methods in question. I have not had success in this question.

  • 1

    No. You putting the print After calling an asynchronous function that does not have the await, it will print without waiting for the functions to finish. Try putting the print inside the function loadLocalesAndVehiclesLists and you’ll see what I say. I suggest you take a look at codelabs that Linkei in the answer, to better understand this part, or ask another question here on the site.

  • @Milhomens here you can see a reply in Portuguese on the subject as well.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.