Search code examples
flutterfirebasedartriverpod

Why is the provider constantly in a "loading" state, if I take off the word "const"?


I'm using a StreamProviderFamily

`ref.watch(getReceitasRefeicaoProvider(  const ReceitasParams(
                  tipo: 'meat',
                  maxPreco: 10000,
                  minLikes: 0,
                  maxCalorias: 100000,
                  maxtempo: 1000)))
              .when(`

to display a user's recipes. At first I used "const RecipesParams" as in the code shown above and everything works perfectly. However when I remove the "const"

`ref.watch(getReceitasRefeicaoProvider(ReceitasParams(
                  tipo: 'meat',
                  maxPreco: 10000,
                  minLikes: 0,
                  maxCalorias: 100000,
                  maxtempo: 1000)))
              .when(`

the StreamProvider Family is constantly in a loading state

Controller.dart

final receitaControllerProvider =
    StateNotifierProvider<ReceitaController, bool>((ref) {
  final receitaRepository = ref.watch(receitaRepositoryProvider);
  final storageRepository = ref.watch(storageRepositoryProvider);
  return ReceitaController(
      receitaRepository: receitaRepository,
      ref: ref,
      storageRepository: storageRepository);
});

final getReceitasRefeicaoProvider = StreamProvider.family<List<Receita>, ReceitasParams>((ref, ReceitasParams params) {
  final postController = ref.watch(receitaControllerProvider.notifier);
  return postController.getReceitasRefeicao(params.tipo, params.maxPreco, params.minLikes, params.maxCalorias, params.maxtempo);
});

Stream<List<Receita>> getReceitasRefeicao(
      String tipo, int maxPreco, int minLikes, int maxCalorias, int maxtempo) {
            return _receitaRepository.getReceitasRefeicao(tipo,maxPreco,minLikes,maxCalorias,maxtempo);
      }

repository.dart

 Stream<List<Receita>> getReceitasRefeicao(
      String tipo, int maxPreco, int minLikes, int maxCalorias, int maxtempo) {
    return _receitas.where('refeicoes', arrayContains: tipo).snapshots().map(
          (event) => event.docs
              .map((e) => Receita.fromMap(e.data() as Map<String, dynamic>))
              .where((receita) {
            final preco = int.tryParse(receita.preco);
            final calorias = int.tryParse(receita.calorias);
            final tempo = int.tryParse(receita.tempo);
            return preco != null &&
                calorias != null &&
                tempo != null &&
                tempo < maxtempo &&
                preco < maxPreco &&
                receita.likes.length >= minLikes &&
                calorias < maxCalorias;
          }).toList(),
        );
  }

I cannot understand why.


Solution

  • If you remove const, but don't set up a proper == and hashCode for your ReceitasParams, then every instance of that is != to any other instance of that, and you'll get a brand new provider every time, even if the params were the same.

    So yes, the solution is that you must implement == and hashCode so that things that are equal are also ==.