Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Learn Reading vs Watching State | Provider Essentials
Flutter State Management Fundamentals

bookReading vs Watching State

Understanding how to access provider state is essential for managing your Flutter app's behavior efficiently. In Provider, you often need to decide between context.read and context.watch when accessing a provider's value. The choice between these two methods determines how your widget responds to changes in the provider's state.

Use context.read<T>() when you want to access the current value of a provider without rebuilding your widget when that value changes. This is ideal for situations where you only need the value once, such as in a button's onPressed callback.

Use context.watch<T>() when you want your widget to rebuild automatically whenever the provider's value changes. This is the right choice for widgets that display or depend on the provider's value in their build method.

main.dart

main.dart

copy
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; void main() { runApp( ChangeNotifierProvider( create: (_) => Counter(), child: const MyApp(), ), ); } class Counter extends ChangeNotifier { int value = 0; void increment() { value++; notifyListeners(); } } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return const MaterialApp( home: CounterScreen(), ); } } class CounterScreen extends StatelessWidget { const CounterScreen({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Read vs Watch Example')), body: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const CounterDisplay(), const SizedBox(height: 20), IncrementButton(), ], ), ); } } class CounterDisplay extends StatelessWidget { const CounterDisplay({super.key}); @override Widget build(BuildContext context) { final count = context.watch<Counter>().value; return Text( 'Counter: $count', style: const TextStyle(fontSize: 24), ); } } class IncrementButton extends StatelessWidget { @override Widget build(BuildContext context) { return ElevatedButton( onPressed: () { // Use context.read to access the provider without rebuilding this widget context.read<Counter>().increment(); }, child: const Text('Increment'), ); } }

In the example above, the CounterDisplay widget uses context.watch<Counter>() to listen for changes in the Counter provider. This means that whenever the counter value updates, CounterDisplay will rebuild and show the latest value. On the other hand, the IncrementButton widget uses context.read<Counter>() in its onPressed callback. This allows the button to increment the counter without causing itself to rebuild when the counter changes.

This difference is important: using context.watch in a widget's build method ensures the widget stays up to date with provider changes, while using context.read is best for event handlers or callbacks where you do not want the widget to rebuild. By understanding when to use each, you can optimize your app's performance and avoid unnecessary widget rebuilds.

question mark

Which statement best describes the difference between context.read and context.watch in Provider?

Select the correct answer

Everything was clear?

How can we improve it?

Thanks for your feedback!

SectionΒ 3. ChapterΒ 3

Ask AI

expand

Ask AI

ChatGPT

Ask anything or try one of the suggested questions to begin our chat

Suggested prompts:

Can you explain more about when to use context.read vs context.watch?

What happens if I use context.read in the build method?

Can you give more examples of using Provider in Flutter?

bookReading vs Watching State

Swipe to show menu

Understanding how to access provider state is essential for managing your Flutter app's behavior efficiently. In Provider, you often need to decide between context.read and context.watch when accessing a provider's value. The choice between these two methods determines how your widget responds to changes in the provider's state.

Use context.read<T>() when you want to access the current value of a provider without rebuilding your widget when that value changes. This is ideal for situations where you only need the value once, such as in a button's onPressed callback.

Use context.watch<T>() when you want your widget to rebuild automatically whenever the provider's value changes. This is the right choice for widgets that display or depend on the provider's value in their build method.

main.dart

main.dart

copy
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; void main() { runApp( ChangeNotifierProvider( create: (_) => Counter(), child: const MyApp(), ), ); } class Counter extends ChangeNotifier { int value = 0; void increment() { value++; notifyListeners(); } } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return const MaterialApp( home: CounterScreen(), ); } } class CounterScreen extends StatelessWidget { const CounterScreen({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Read vs Watch Example')), body: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const CounterDisplay(), const SizedBox(height: 20), IncrementButton(), ], ), ); } } class CounterDisplay extends StatelessWidget { const CounterDisplay({super.key}); @override Widget build(BuildContext context) { final count = context.watch<Counter>().value; return Text( 'Counter: $count', style: const TextStyle(fontSize: 24), ); } } class IncrementButton extends StatelessWidget { @override Widget build(BuildContext context) { return ElevatedButton( onPressed: () { // Use context.read to access the provider without rebuilding this widget context.read<Counter>().increment(); }, child: const Text('Increment'), ); } }

In the example above, the CounterDisplay widget uses context.watch<Counter>() to listen for changes in the Counter provider. This means that whenever the counter value updates, CounterDisplay will rebuild and show the latest value. On the other hand, the IncrementButton widget uses context.read<Counter>() in its onPressed callback. This allows the button to increment the counter without causing itself to rebuild when the counter changes.

This difference is important: using context.watch in a widget's build method ensures the widget stays up to date with provider changes, while using context.read is best for event handlers or callbacks where you do not want the widget to rebuild. By understanding when to use each, you can optimize your app's performance and avoid unnecessary widget rebuilds.

question mark

Which statement best describes the difference between context.read and context.watch in Provider?

Select the correct answer

Everything was clear?

How can we improve it?

Thanks for your feedback!

SectionΒ 3. ChapterΒ 3
some-alt