Flutter: Disposing of resources in @riverpod generated provider

961 Views Asked by At

I am using riverpod_generator in my Flutter app to generate a provider for a controller that I use. The controller is actually a Notifier.

I am wondering where is the correct place in the controller to set up the disposal of resources (in this case, a BehaviorSubject, and its stream's subscription.

Is it ok to do it in the build() method, as I have in the included code? Thanks

part "provider.g.dart";

final PlayersSearchFiltersValue _initialFilters = PlayersSearchFiltersValue(
  searchTerm: "",
);

@riverpod
class PlayersSearchAppController extends _$PlayersSearchAppController
    implements PlayersSearchController {
  late final PlayersService playersService =
      ref.read(playersAppServiceProvider);

  final BehaviorSubject<PlayersSearchFiltersValue> _filtersSubject =
      BehaviorSubject();
  late StreamSubscription<PlayersSearchFiltersValue> _filtersSubscription;
  StreamSink<PlayersSearchFiltersValue> get _filtersSink =>
      _filtersSubject.sink;

  @override
  AsyncValue<List<PlayerModel>> build() {
    _initializeController();
    return AsyncValue.data([]);
  }

  /// rest of the code

  void _initializeController() {
    _filtersSubscription = _filtersSubject.stream
        .debounceTime(Duration(milliseconds: 500))
        .listen((event) {
      _onSearchPlayers(event);
    });

    ref.onDispose(() async {
      await _filtersSubscription.cancel();
      await _filtersSubject.close();
    });
  }
}
1

There are 1 best solutions below

2
On

Yes, this will work great. The only thing, perhaps, is to define a separate _dispose method and allocate this piece of code to it in order to share responsibilities.


  @override
  AsyncValue<List<PlayerModel>> build() {
    _initializeController();
    _dispose();
    return AsyncValue.data([]);
  }

  void _dispose() {
    ref.onDispose(() async {
      await _filtersSubscription.cancel();
      await _filtersSubject.close();
    });
  }

  void _initializeController() {
    _filtersSubscription = _filtersSubject.stream
        .debounceTime(Duration(milliseconds: 500))
        .listen((event) {
      _onSearchPlayers(event);
    });
  }

Also, you should remember that generator by default creates providers that dispose their state (as with the dispose modifier). To change this behavior, use:

@Riverpod(keepAlive: true)