Bringing back contex.read and context.watch for riverpod

Overview

This package brings back the context extensions for riverpod that were discontinued in version 1.0.0.

  • To read any provider, do context.read(myProvider)
  • To watch any provider, do context.watch(myProvider)

This package is meant to be used alongside riverpod and offers an alternative to the official ConsumerWidget and ConsumerStatefulWidget.

Getting Started

This assumes you already have flutter_riverpod (or hooks_riverpod) set up.

First, add riverpod_context as a dependency.

flutter pub add riverpod_context

Next, add InheritedConsumer underneath the root ProviderScope:

// Before
ProviderScope(
  child: MyApp(),
)
// After
ProviderScope(
  child: InheritedConsumer(
    child: MyApp(),
  ),
)

That's all.

Context Extensions

riverpod_context provides four convenient context extensions to interact with your providers.

context.read

context.read can be used anywhere without any special consideration. It naturally supports any providers, provider families as well as the new .select() syntax.

Widget build(BuildContext context) {
  // this won't rebuild based on 'myValue'
  String myValue = context.read(myProvider);
  return Text(myValue);
}

context.watch

context.watch watches the provider and triggers a rebuild of the given context when the providers state changes. It again supports any providers, provider families as well as the new .select() syntax.

Widget build(BuildContext context) {
  // this will rebuild each time 'myValue' changes
  String myValue = context.watch(myProvider);
  return Text(myValue);
}

🚨 There are a few important considerations to make when using context.watch. With those, you can also safely use any .autoDispose providers.

1. Only use inside build()

context.watch can only be used inside the build() method of a widget. Especially interaction callbacks (like onPressed) and StatefulWidgets initState, didChangeDependencies and other lifecycle handlers are not allowed.

2. Be cautious when conditionally watching providers

It is possible to conditionally watch providers. This is the case when context.watch may not be called on every rebuild.

Widget build(BuildContext context) {
  if (myCondition) {
    return Text(context.watch(myProvider));
  } else {
    return Container();
  }
}

In this example, when myCondition is false, context.watch is not called. This leads to an issue where the dependencies of the provider are not clearly defined.

It is important to make sure that this does not happen, since it can lead to leaking memory and wrong behavior!

Preventing this is however pretty simple.

If there exists another context.watch on the same context, this issue is resolved. Generally speaking, it requires at least one context.watch call on every build to be safe.

If in the example above, the myCondition actually comes from another context.watch call, you are safe.

Widget build(BuildContext context) {
  if (context.watch(myConditionProvider)) {
    // don't worry about this being called conditionally, 
    // we already have called context.watch once before
    return Text(context.watch(myProvider));
  } else {
    return Container();
  }
}

If not, use context.prime().

3. Or use context.prime() when conditionally watching providers

If context.watch is - under certain conditions - not called on every rebuild, you have to "prime" the context for the missing provider. This can be done using a simple context.prime() call.

In the previous example, this can be placed either in the else, or unconditionally at the top. It also has no effect to do it multiple times.

Widget build(BuildContext context) {
  context.prime(); // option 1: always prime
  if (myCondition) {
    return Text(context.watch(myProvider));
  } else {
    context.prime(); // option 2: prime to account for missing context.watch call
    return Container();
  }
}

As a rule just remember this:

Wherever you use context.watch conditionally, make sure to either have another unconditional context.watch or use context.prime on the same context.

Or in other words:

You are safe if on each rebuild there always is at least one call to either context.watch or context.prime.

context.refresh

context.refresh refreshes any provider.

Widget build(BuildContext context) {
  return TextButton(
    onPressed: () {
      context.refresh(myProvider);
    },
    child: const Text('Refresh'),
  );
}

context.listen

context.listen Listens to a provider without triggering a rebuild. This can be used inside the build() method or in the didChangeDependencies() of a stateful widget.

Widget build(BuildContext context) {
  
  context.listen(myProvider, (previous, value) {
    // do something
  });
  
  return SomeWidget();
}
Idempotent listeners

There will only ever be a single active listener for a specific context, meaning that calling context.listen multiple times for the same provider will only have the last listener active. Only because of this it is safe to use context.listen inside the build() method across rebuilds.

You can set fireImmediate: true to immediately fire the listener once. This will be ignored when re-listening to a provider, i.e. after a rebuild.

Widget build(BuildContext context) {

  // across multiple rebuilds, there will only exist a single listener on this provider
  // only on the first build, the listener will fire immediately
  context.listen(myProvider, (previous, value) {
    // do something
  }, fireImmediately: true);
  
  return SomeWidget();
}
Closing listeners

All listeners will only be closed when the context is disposed. Therefore it has no effect to call context.listen conditionally, especially with .autoDispose providers.

There are two ways to control the closing of a listener:

  • By using context.unlisten you can close the active listener on a provider.
  • When wanting more control over a listener, use context.subscribe.
Widget build(BuildContext context) {

  if (myCondition) {
    context.listen(myProvider, (previous, value) {
      // do something
    });
  } else {
    // this will remove the active listener on this provider
    // and properly dispose an .autoDispose provider
    context.unlisten(myProvider);
  }
  
  return SomeWidget();
}

context.subscribe

context.subscribe listens to a provider and returns the ProviderSubscription. Use this when you need to manually manage the subscription of a provider.

  • This can be used wherever you have a BuildContext, even in the initState() method.
  • Make sure to call subscription.close() when the listener is no longer needed.
class MyWidgetState extends State<MyWidget> {
  
  late ProviderSubscription subscription;
  
  @override
  void initState() {
    // store the returned subscription in a variable
    subscription = context.subscribe(myProvider, (previous, value) {
      // do something
    });
  }
  
  // ...
  
  @override dispose() {
    // make sure to properly close the subscription
    subscription.close();
  }
}
You might also like...

A customizable Flutter library that provides a circular context menu

A customizable Flutter library that provides a circular context menu

Flutter Pie Menu 🥧 A customizable Flutter library that provides a circular context menu similar to Pinterest's. Usage Wrap the widget that will react

Jan 4, 2023

Build context - Access most used properties in your BuildContext instance.

Languages: English | Brazilian Portuguse BuildContext Access most used properties in your BuildContext instance. This package relies on Dart's extensi

Dec 11, 2022

Flutter project being built in the context of Smart India Hackathon { SIH }.

e_chardham_yatra A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started

Dec 29, 2022

Flutter In-Context Editing example

Flutter In-Context Editing example

Flutter In-Context Editing example Instantly see how your translations fit on a real device without unnecessary app builds Setup Clone the repo Run fl

Jun 3, 2022

FlutterNavigator is a dart library for dealing with the Navigator API without a build context

FlutterNavigator is a dart library for dealing with the Navigator API without a build context. This package wraps the NavigatorKey and provides a cleaner service for navigating without context in your flutter application.

Oct 1, 2022

PsTube - Watch and download videos without ads

PsTube - Watch and download videos without ads

PsTube - Formerly FluTube Watch and download videos without ads Features Beautiful user interface Lightweight and fast No Login Required Keep your lik

Dec 21, 2022

A Flutter App To Watch Anime Online With No Ads

A Flutter App To Watch Anime Online With No Ads

Tako Play A Mobile App to Watch Anime With No ADS !! . Please Do not put Tako-Pl

Dec 22, 2022

Arispewdie - Flutter app to watch LIVE subscriber count of PewDiePie vs T-Series

Arispewdie - Flutter app to watch LIVE subscriber count of PewDiePie vs T-Series

PewDiePie VS T-Series Flutter app to watch LIVE subscriber count of PewDiePie vs

Jan 10, 2022

Flutter-watchtips - Flutter App (Embedded Watch Kit app with iOS version)

Flutter-watchtips - Flutter App  (Embedded Watch Kit app with iOS version)

watchtips Update Version 2.2 The Watch tips project has been updated again, The interface has been tidied up and a seperate value for the tip cost has

Dec 31, 2022
Owner
Kilian Schulte
Computer Science Student & Flutter Freelancer
Kilian Schulte
Stop Watch - Stop Watch Timer in Flutter

timerapp A new Flutter project. Getting Started This project is a starting point

MD Omar Faruk. 0 Jan 27, 2022
Cupertino back gesture - Flutter package to set custom width of iOS back swipe gesture area

cupertino_back_gesture A Flutter package to set custom width of iOS back swipe gesture area. Usage To use this package, add cupertino_back_gesture as

null 28 Dec 7, 2022
Riverpod Messages Listener: A message notification listener for apps build with Riverpod

Riverpod Messages Listener Hello all, this is the home page of riverpod_messages package, a message notification listener for apps build with Riverpod

Fabrizio Tognetto 4 Dec 8, 2022
A GraphQL client for Flutter, bringing all the features from a modern GraphQL client to one easy to use package. Built after react apollo

Flutter GraphQL Table of Contents Flutter GraphQL Table of Contents About this project Installation Usage GraphQL Provider [Graphql Link and Headers]

Snowball Digital 45 Nov 9, 2022
A GraphQL client for Flutter, bringing all the features from a modern GraphQL client to one easy to use package.

GraphQL Flutter ?? Bulletin See the v3 -> v4 Migration Guide if you're still on v3. Maintenance status: Low. Follow #762 for updates on the planned ar

Zino & Co. 3.1k Jan 5, 2023
The easiest way to use navigation, context less and useful methods.

Starlight Utils The easiest way to use navigation, context less and useful methods. Features Name Status Context Less Navigation Service ✅ Context Les

Ye Myo Aung 5 Jul 10, 2022
Easy nav - A simple wrapper around flutter navigator, dialogs and snackbar to do those things without context

EasyNav Just a simple wrapper around flutter navigator, dialogs and snackbar to

Abdul Shakoor 2 Feb 26, 2022
a mobile app to search for information and watch movie, series and TV show trailers

inWatch Just a clean architecture app, to get trailers and informations of movies, series and TV shows, made with Getx, omdb API and Flutter sdk. The

Augusto da Silva 20 Nov 10, 2022