Home > Net >  How to dynamically create providers at runtime with Riverpod?
How to dynamically create providers at runtime with Riverpod?

Time:10-21

In my flutter app I am exploring a transition from the Provider package to Riverpod. The app is quite simple: it fetches a list of objects from a database, and allows the user to change these objects's characteristics. It is thus pretty similar to the official TODO example app.

I see however that such app does not provide an individual provider for each TODO item as I'd expect, but it rather declares a global provider the entire TODO list. I found such approach odd, as it requires that everytime a TODO item changes the entire list UI needs to be rebuilt (unless I am mistaken).

Reading through other examples, I see that all providers are always declared globally. Does this mean it is not possible with Riverpod to create new providers at runtime? (As in my case, from a list of objects returned by an API?)

I'm sorry if it is a trivial question, but I couldn't find any related example or documentation about this.

EDIT: I was mistaken indeed. The entire list is NOT rebuilt in its entirety. See answers below.

CodePudding user response:

The example is actually using a provider called _currentTodo:

final _currentTodo = Provider<Todo>((ref) => throw UnimplementedError());

As you see, at the time of declaring this, there is no return value and instead we're throwing UnimplementedError().

When it comes to populating a single TodoItem, we first wrap it with a ProviderScope widget. This allows us to override the value that _currentTodo provides with another value:

ProviderScope(
  overrides: [
    _currentTodo.overrideWithValue(todos[i]),
  ],
  child: const TodoItem(),
),

This allows us to use const when constructing TodoItem instead of passing the todos[i] in the constructor. This ensures that when we edit todos, only the impacted widgets rebuild, instead of the entire list of items.

Later on we can consume the todo from the TodoItem build method:

final todo = ref.watch(_currentTodo);

CodePudding user response:

Dynamically creating providers at runtime is an anti-pattern. Source: I'm the author of Riverpod.

Providers should purposefully be globals.
If you don't respect that, you could end up with memory leaks or break some of the upcoming debug tools.

The fact that providers are global is not a problem though.
Riverpod is built around that condition and offers various solutions to the problems you'll face when building applications using this strategy.

For example, if the very example you shared (the official TODO example app), the example correctly does not rebuild the entire application when updating the list of todos.

I invite you to put a print statement inside the TodoItem widget (here). You'll see that when updating todos, only the corresponding TodoItem updates.

  • Related