Flutter’s state restoration lets you to preserve and restore the state of widgets in your app. This is especially useful when users switch between apps or when your app is closed and then reopened.
State restoration preserves user interactions and progress, ensuring a seamless experience. Users can resume where they left off, even after interruptions or app restarts.
Read about the variety of Flutter App Development Services offered by Mobikul.
Some basics Terminology
- RestorationManager: is responsible for managing the state restoration process. It works in conjunction with
RestorationMixin
andRestorationScope
to save and restore the state of widgets, usually we don’t need to use it directly. RestorationMixin
: This mixin, which can be applied to a StatefulWidget, allows you to save and restore the state of a widget.RestorationScope
: A widget that defines a boundary within which state restoration is managed.- RestorationBucket: is like a storage place where the RestorationMixin saves all the restoration data.
- RestorationScopeId: restorationScopeId is a MaterialApp attribute that has to be specified with a unique string for your app. in our example we have used “root”.
- RestorableProperty: is used instead of a regular variable (double, int, and String etc), state is stored inside a RestorableProperty at runtime.
- registerForRestoration: is a function that is used to register a restorable property for state restoration, accept two arguments restorableProperty and unique string as restorationId.
- Restoration ID: is a property used to uniquely identify a widget’s state.
Implementation
- Provide restorationScopeId property in MaterialApp (“root” in our example).
- Extends Stateful widget with RestorationMixin class and implement its members.
- Create restorable properties and use it instead of the common Dart’s data type.
- Register restorable properties for restoration.
First, go to Developer options and enable the “don’t keep activities” option as shown below:
Implementation
Enable the “don’t keep activities” option as shown.
This will make it look like the device doesn’t have enough memory, and the device will kill all activities immediately after you leave it.
Now, add a unique restorationScopeId
inside your material app (I have used “root“).
1 2 3 4 5 6 7 8 9 |
MaterialApp( debugShowCheckedModeBanner: false, restorationScopeId: "root", theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: false, ), home: const SignUpFormView(), ); |
Now, Create Stateful widget (SignUpFormView) and add the RestorationMixin with _SignUpFormViewState as shown below :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
class SignUpFormView extends StatefulWidget { const SignUpFormView({Key? key}) : super(key: key); @override State<SignUpFormView> createState() => _SignUpFormViewState(); } class _SignUpFormViewState extends State<SignUpFormView> with RestorationMixin{ final RestorableTextEditingController _nameController = RestorableTextEditingController(); final RestorableBool _isSubscribe = RestorableBool(false); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text("Registration Form"), ), body: const Text("Sign up form") ); } @override String get restorationId => 'signup_page'; @override void restoreState(RestorationBucket? oldBucket, bool initialRestore) { registerForRestoration(_nameController, 'name_controller'); registerForRestoration(_isSubscribe, 'isSubscribe'); } } |
RestorableTextEditingController: RestorableTextEditingController used instead of TextEditingController to save the state of text field.
RestorableBool: RestorableBoolean value used instead of bool.
Need to implement the getter restorationId and restoreState function of RestorationMixin :
registerForRestoration: function that register the restorable properties with unique restorationId.
getter restorationId: return the string “signup_page” This value serves as the unique identifier for the state of SignUpFormView.
You can learn about widgets states in flutter.
Lastly, create a simple view having a TextFormField and Checkbox widget inside body of Scaffold.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
Scaffold( appBar: AppBar( title: const Text("Registration Form"), ), body: Padding( padding: const EdgeInsets.all(12), child: Column( children: [ TextFormField( controller: _nameController.value, decoration: const InputDecoration( labelText: "Name" ), ), Row( children: [ Checkbox(value: _isSubscribe.value, onChanged: (bool? val){ setState(() { _isSubscribe.value = val ?? false; }); }), const Text("Subscribe to our services") ], ), ElevatedButton(onPressed: (){ }, child: const Text("Submit")) ], ), ), ); |
Access the restorable property values using (.value) and assign to TextFormField controller and Checkbox value property as shown in above example.
Build and run the project.
Output
State Restoration
We have successfully restored the state of application as :
- When the application is minimized or moved to the background, the operating system terminates the application.
- After clicking on minimized app, the operating system resumes the application.
- We just got back the text of the form we have filled out and the checkbox was set to a bool value.
Restoration of route stack
we can restore the routes when we are navigating from one screen to another screen we have to use restorablePush function as :
1 2 3 4 5 |
ElevatedButton( onPressed: () { Navigator.restorablePush(context, _myRouteBuilder); }, child: const Text("Submit")) |
Elevated button onPressed property we have used Navigator.restorablePush which provide restorable route stack feature.
Navigation and routing in flutter.
Create static method _myRouteBuilder outside the build method of SignUpFormView widget.
1 2 3 4 5 |
static Route<void> _myRouteBuilder(BuildContext context, Object? arguments) { return MaterialPageRoute<void>( builder: (BuildContext context) => const SubmitView(), ); } |
Create a simple dart class (SubmitView) to show another screen on navigation by clicking submit button.
Read more about state management in flutter.
Output of Navigation restoration
We have successfully restored the route when the move to background and resume again, we got same route as SubmitView.
Navigation Restoration
Conclusion
Thanks for reading this article ❤️
I hope this blog will help you to learn about how to restore state in flutter and you will be able to implement it. For more updates, make sure to keep following Mobikul Blogs to learn more about flutter and android.
Happy Learning ✍️
want to know about SavedState in android.
References
https://hrishikeshpathak.com/blog/flutter-state-restoration/