ScopedProvider<Listened> class

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 Provider.family 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:

ListView.builder(
  itemBuilder: (context, index) {
    return ProviderScope(
      overrides: [
        currentProductIndex.overrideWithValue(index),
      ],
      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);

  @override
  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>'));
Inheritance
Annotations
  • @sealed

Constructors

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

Properties

argument Object?
If this provider was created with the .family modifier, argument is variable used.
no setterinherited
debugId String
A unique identifier for this provider, used by devtools to differentiate providers
latefinalinherited
from Family<dynamic, dynamic, dynamic, ProviderReference, RootProvider>?
If this provider was created with the .family modifier, from is the .family instance.
no setterinherited
hashCode int
The hash code for this object.
no setterinherited
name String?
A custom label for providers.
finalinherited
runtimeType Type
A representation of the runtime type of the object.
no setterinherited

Methods

create(covariant _ScopedProviderElement ref) → Listened
override
createElement() → _ScopedProviderElement<Listened>
An internal method that defines how a provider behaves.
override
createState() → _ScopedProviderState<Listened>
An internal method that creates the state of a provider.
override
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
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.
inherited

Operators

operator ==(Object other) bool
The equality operator.
inherited