Search code examples
flutterdartproviderriverpod

Dart Riverpod merging two providers of the same type


I am looking for a way to combine two providers (that both emit the same type of values) into one such that the resulting provider emits the most recent value emitted by either of the two input providers.

Example:

import 'package:riverpod/riverpod.dart';

// Example StateNotifier for a simple counter.
class Counter extends StateNotifier<int> {
  Counter() : super(0);

  void increment() {
    state++;
  }
}

// Create multiple providers of the same type.
final counterProvider1 = StateNotifierProvider<Counter, int>((ref) => Counter());
final counterProvider2 = StateNotifierProvider<Counter, int>((ref) => Counter());

// Create a provider that combines the latest values.
final mergeCounterProvider = Provider<int>((ref) {
  final counter1 = ref.watch(counterProvider1);
  final counter2 = ref.watch(counterProvider2);

  // TODO return the latest value
  return ???;
});

The mergeCounterProvider would need to update and emit the value of the latest updated counter.

EDIT:

Adapted solution from @RandalSchwartz's answer: https://dartpad.dev/?id=87a704475672f256810c590cac9be93f


Solution

  • Use ref.listen for both, setting that up in build/create, and pushing the updated value to ref.state. It'll automatically be the most recent of the two streams

    final mergeCounterProvider = Provider<int?>((ref) {
      ref
        ..listen(counterProvider1, (_, value) {
          ref.state = value;
        })
        ..listen(counterProvider2, (_, value) {
          ref.state = value;
        });
      return null;
    });