Как прослушивать значения StreamProvider у другого провайдера и не получать дубликатов

#flutter #stream #riverpod

#flutter #поток #riverpod

Вопрос:

Я хочу прослушивать коллекцию firebase в режиме реального времени с помощью StreamProvider из Riverpod и считывать значения у другого провайдера, но ничего из того, что я пробовал, не работает.

 /// StreamProvider
final firstProvider = StreamProvider.autoDispose((ref) async* {
  final stream = FirebaseFirestore.instance
      .collection('someCollection')
      .orderBy('timestamp', descending: true)
      .snapshots()
      .distinct();

  await for (final value in stream) {
    print('value: $value');
    yield value;
  }
}

final secondProvider = FutureProvider.autoDispose((ref) async {
  final first_provider = await ref.watch(firstProvider);
  print(first_provider .whenData((value) => value.docChanges.length));
  ...
});
 

Я думал, что при использовании docChanges я получу только новые данные, но вместо этого они дублируются при каждой перестройке.

Есть идеи относительно того, что я делаю неправильно?

Ответ №1:

С вашими провайдерами все в порядке. Однако docChanges возвращает массив документов, измененных с момента предыдущего снимка, и, если это первый снимок, будет содержать все документы.

Вы используете autoDispose модификатор для своих провайдеров. Итак, если виджет (или другой провайдер и т.д.), С которого вы читаете своих провайдеров, удален, ваши провайдеры также будут удалены. Это приведет к новому чтению из вашей базы данных, что приведет к возврату всех документов docChanges .

Попробуйте удалить autoDispose модификатор и посмотреть, что произойдет.

Комментарии:

1. Привет, спасибо за ваш ответ! Да, я действительно уже сделал это и решил проблему, хотя я не думаю, что это правильный подход. С помощью модификатора .autodispose у нас есть новое свойство ref.mantainstate, которое по умолчанию равно false . Согласно документам riverpod.dev/docs/concepts/modifiers/auto_dispose , установив для этого значение true, мы не будем запускать какие-либо другие запросы при изменении экранов / перестроении виджетов.

2. Рад, что вы смогли это решить. Я бы сказал, что подход зависит от варианта использования. Если maintainState работает для вас здесь, я бы сказал, отлично, обычно лучше использовать autoDispose, если вы можете. Хотя, безусловно, бывают случаи, когда его не стоит использовать.

Ответ №2:

Если у кого-то такая же проблема, я решил ее, установив дополнительное свойство, maintainState , которое autoDispose предоставляет модификатор.

 final firstProvider = StreamProvider.autoDispose((ref) async* {
  final stream = FirebaseFirestore.instance
      .collection('someCollection')
      .orderBy('timestamp', descending: true)
      .snapshots()
      .distinct();
  
  ref.mantainstate = true;

  await for (final value in stream) {
    print('value: $value');
    yield value;
  }
}
 

Комментарии:

1. Поскольку это решило вашу проблему, вы должны пометить это как принятый ответ.