Flutter – local state vs App-wide state
Local State (sometimes called UI state or Ephemeral State): It is a state which can be manageable in a single widget. There is no need for state management techniques(Bloc, redux, etc ) on this kind of state a Stateful Widget would suffice.
Examples:
Current page in a page view, current tab in the navigation bar.
Dart
import 'package:flutter/material.dart' ; void main() { runApp(MyApp()); } class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { List<Widget> _spaces = <Widget>[ Text( 'Home Page' , style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold)), Text( 'Search Page' , style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold)), Text( 'Account Page' , style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold)), ]; // local variable int _index = 0; @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false , title: 'Beginner For Beginner' , theme: ThemeData( primarySwatch: Colors.green, ), darkTheme: ThemeData.dark(), home: Scaffold( appBar: AppBar( leading: Icon(Icons.backspace), title: Text( "Beginner for Beginner" ), centerTitle: true , ), bottomNavigationBar: BottomNavigationBar( currentIndex: _index, onTap: (newIndex) { setState(() { // changing in widget _index = newIndex; print( '$_index' ); }); }, items: [ BottomNavigationBarItem( label: "Home" , icon: Icon(Icons.home), ), BottomNavigationBarItem( label: "Search" , icon: Icon(Icons.search), ), BottomNavigationBarItem( label: "Account" , icon: Icon(Icons.person), ), ], ), body: Center(child: _spaces.elementAt(_index)), ), ); } } |
Output:
App-wide State: State that is not local and is accessible across our application, is what is known as App-wide state or Shared state.
Examples: Notifications in a social networking app.
Shopping cart state in an e-commerce app.
Step 1: First add Provider dependency in pubspec.yaml file in the lib folder.
Dart
dev_dependencies: provider: ^4.3.2 |
We have added the dependency for Provider in our pubspec.yaml file located in the lib folder in dependencies as shown above:
Now click pub get or save the file so the package gets fetched.
Step 2: Using provider we notify changes and update the state of counter :
Dart
import 'package:flutter/material.dart' ; import 'package:provider/provider.dart' ; void main() { runApp( ChangeNotifierProvider( create: (context) => Counter(), child: MyApp(), ), ); } class Counter with ChangeNotifier { int value = 0; void increment() { value += 1; notifyListeners(); } } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false , title: 'Beginner For Beginner' , theme: ThemeData( primarySwatch: Colors.green, ), darkTheme: ThemeData.dark(), home: MyHomePage(), ); } } class MyHomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( leading: Icon(Icons.backspace), title: Text( "Beginner for Beginner" ), centerTitle: true , ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text( 'You have pushed the button this many times:' ), Consumer<Counter>( builder: (context, counter, child) => Text( '${counter.value}' , style: TextStyle(fontSize: 26), ), ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: () { var counter = context.read<Counter>(); counter.increment(); // calling increment on tap }, tooltip: 'Increment' , child: Icon(Icons.add), ), ); } } |
Output:
To better understand the difference between an App state and Ephemeral State look into the following diagram: