ScopedProvider<Listened> class Null safety

A provider that may behave differently for a specific part of the application.

A common use-case for ScopedProvider is to avoid having to pass the argument of a in the widget tree.

More specifically, we may have a ListView that wants to render of list of products. But for both performance and simplicity, we do not want to pass the product id/index to the item's constructor.

In that situation, we could use ScopedProvider, in combination with ProviderScope, to allow our items to access the id/index, without receiving it from its constructor.

For this, we first need to define our ScopedProvider like any other provider:

final currentProductIndex = ScopedProvider<int>((_) => throw UnimplementedError());

Note: We made our ScopedProvider throw by default, as our list items by design requires an index to be specified. Another possibility would be to return null and have the item handle the null scenario.

Then, inside our ListView, we will use ProviderScope to override the value exposed by ScopedProvider:

  itemBuilder: (context, index) {
    return ProviderScope(
      overrides: [
      child: const ProductItem(),

This code means that for the first item in our ListView, currentProductIndex will return 0; whereas for the second item, it will return 1, ...

Finally, we can read the item index inside our ProductItem:

class ProductItem extends ConsumerWidget {
  const ProductItem({Key? key}): super(key: key);

  Widget build(BuildContext context, ScopedReader watch) {
    final index = watch(currentProductIndex);
    // do something with the index


Now, our ProductItem was able to obtain the product index it is associated with. The interesting aspect of such code is that ProductItem was instantiated using the const keyword, but still renders dynamic content.

What this means is, even if ListView rebuilds, our ProductItem will not rebuild unless what it uses changed.

ScopedProvider with no default behavior

A common use-case with ScopedProvider is to not provide a default behavior, and instead always override the provider inside a ProviderScope.

In this situation, what we can do is pass null instead of a function to ScopedProvider:

final example = ScopedProvider<int>(null);

This is equivalent to:

final example = ScopedProvider<int>((watch) => throw UnsupportedError('<some error message>'));


ScopedProvider(Listened _create(ScopedReader watch)?, {String? name})
A provider that may behave differently for a specific part of the application. [...]


argument Object?
If this provider was created with the .family modifier, argument is variable used.
read-only, inherited
debugId String
A unique identifier for this provider, used by devtools to differentiate providers [...]
final, read / write, inherited, late
from Family<dynamic, dynamic, dynamic, ProviderReference, RootProvider>?
If this provider was created with the .family modifier, from is the .family instance.
read-only, inherited
hashCode int
The hash code for this object. [...]
@nonVirtual, read-only, inherited
name String?
A custom label for providers. [...]
final, inherited
runtimeType Type
A representation of the runtime type of the object.
read-only, inherited


create(covariant _ScopedProviderElement ref) → Listened
createElement() → _ScopedProviderElement<Listened>
An internal method that defines how a provider behaves.
createState() → _ScopedProviderState<Listened>
An internal method that creates the state of a provider.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a non-existent method or property is accessed. [...]
overrideAs(ScopedCreate<Listened> create) Override
Overrides a ScopedProvider with a different behavior
overrideWithValue(Listened value) Override
Overrides the behavior of a provider with a value. [...]
toString() String
A string representation of this object. [...]


operator ==(Object other) bool
The equality operator. [...]