Johny Gates
Johny Gates

Reputation: 135

Riverpod provider unexpectedly disposing and recreating itself when value of another provider being watched by it is updated

I am creating a simple riverpod based sortable and filterable list having involved majorly 4 providers:

getArticleListProvider:

@riverpod
Future<List<Article>> getArticleList(GetArticleListRef ref) async {
  ref.onCancel(() => print("onCancel: GET_ARTICLE_LIST"));
  ref.onDispose(() => print("onDispose: GET_ARTICLE_LIST"));
  ref.onResume(() => print("onResume: GET_ARTICLE_LIST"));
  print("GET_ARTICLE_LIST provider running");
  await Future.delayed(const Duration(milliseconds: 1500));
  return generateArticles(7);
}

selectedSortTypeProvider:

@riverpod
class SelectedSortType extends _$SelectedSortType {
  @override
  SortType build() => SortType.dateNewestFirst;
  void updateSortType(SortType newSortType) => state = newSortType;
}

selectedFilterTypeProvider:

@riverpod
class SelectedFilterType extends _$SelectedFilterType {
  @override
  FilterType build() {
    ref.onCancel(() => print("onCancel: SELECTED_FILTER_PROVIDER"));
    ref.onDispose(() => print("onDispose: SELECTED_FILTER_PROVIDER"));
    ref.onResume(() => print("onResume: SELECTED_FILTER_PROVIDER"));
    return FilterType.none;
  }

  void updateFilterType(FilterType newFilterType) => state = newFilterType;
}

Note: Have made above providers as Riverpod classes and not StateProvider because riverpod_generator provides no provision for them.

filteredAndSortedArticlesProvider:

@riverpod
Future<List<Article>> filteredAndSortedArticles(
    FilteredAndSortedArticlesRef ref) async {
  ref.onCancel(() => print("onCancel: FILTERED_AND_SORTED_ARTICLES"));
  ref.onDispose(() => print("onDispose: FILTERED_AND_SORTED_ARTICLES"));
  ref.onResume(() => print("onResume: FILTERED_AND_SORTED_ARTICLES"));
  print("running FILTERED_AND_SORTED_ARTICLES provider");

  FilterType filter = ref.watch(selectedFilterTypeProvider);
  SortType sort = ref.watch(selectedSortTypeProvider);
  List<ValueItem> selectedtags = ref.watch(selectedTagListForFilteringProvider);
  List<Article> currentList = await ref.watch(getArticleListProvider.future);

  switch (sort) {
    case SortType.dateOldestFirst:
    currentList.sort((a, b) => a.dateTimeAdded.compareTo(b.dateTimeAdded));
    //...remaing sorting and filtering logic
  }
   return currentList;
}

UI is watching only the filteredAndSortedArticlesProvider using ref.watch() and contains filter and sort buttons.
Now the problem I am facing is that whenever the filter or sort types are changed, the filteredAndSortedArticlesProvider automatically disposes and recreates itself. As of my limited knowledge whenever a provider's values are updated, no providers watching it disposed but are simply recreated with the new values.

Below are the logs:
When project begins to run:

running FILTERED_AND_SORTED_ARTICLES provider
SELECTED_TAG_LIST_PROVIDER USING DEFAULT VALUE [] empty list
GET_ARTICLE_LIST provider running

When SortType is changed using ref.read(selectedSortTypeProvider.notifier).updateSortType(SortType.dateOldestFirst) placed inside onTap function:

onCancel: GET_ARTICLE_LIST
onDispose: FILTERED_AND_SORTED_ARTICLES
running FILTERED_AND_SORTED_ARTICLES provider
onResume: GET_ARTICLE_LIST

When FilterType is changed:

onDispose: FILTERED_AND_SORTED_ARTICLES
running FILTERED_AND_SORTED_ARTICLES provider

I know that I can turn the autoDispose off using @Riverpod(keepAlive:true) annotation but I am bothered with the unexpected behavior (according to me) that providers are disposing & recreating themselves without me even Navigating elsewhere and no listeners were removed either. Kindly provide me with the insights, right approach of doing what I am doing, why is the disposal happening, and other important key things.
Appreciate any help.

Upvotes: 0

Views: 95

Answers (0)

Related Questions