Flutter State Restoration Tool for Devs: Preserve App State with Custom Restoration

Imagine using an app to perform an important task – Completing a lengthy form or switching from one screen to another. However, you get interrupted in the middle, or the phone restarts. What do we have when we are coming back after some time?

You find everything is just as it was!

This is the elegance of state restoration in Flutter, doing exactly what the name suggests, making sure you don’t lose your current task inside the app.

In this blog, you will learn how Flutter supports its developers in preserving the app state by allowing users to resume their work at any session. Also, find how the custom restoration class goes a notch higher to enable developers to manage complex scenarios.

What is State Restoration in Flutter?

State management is a critical aspect of modern mobile application development. But sometimes it fails to address the cases where the system kills the application state, or the user decides to put the application on pause and then continue using it. That is where state restoration is useful – enabling the app to recall where it was before it resumed the state to retain user data across some state changes.

State restoration refers to the process in which the state of an app and the widgets are preserved when the application is closed or it’s no longer in use. If the user comes back into the app, then the state is resumed for the user to continue their progress, thus improving user experience.

Man working on a laptop with code on the screen.

Why is Custom Restoration Required?

Flutter has solutions for state management but there are cases when the whole application state must be saved, which may take more effort. Consider an app with intricate user operations – forms or steps, navigation wings, or input-oriented interfaces.

In such cases, it becomes possible that Flutter’s default restoration program cannot meet app state needs. However, to apply flexible changes to any app state customized state restoration can be the best approach.

Default State Management vs. State Restoration

Flutter provides built-in state management systems, like Provider, Bloc, and Riverpod, which help maintain the state within a running session. However, these systems don’t automatically handle restoration when an operating system closes or suspends an app. State restoration ensures that data is preserved even when the app is completely terminated, offering a more robust state management approach.

Use Cases for State Restoration

State restoration is mandatory in the apps that need to preserve user progress across sessions.

For example:

  • Multi-step forms are long, and users may leave them halfway to resume later.
  • Navigating through several screens of e-commerce or similar apps where users want to return to the last screen they visited.
  • Performing Input-heavy operations in Gaming app interfaces where users want to resume exactly where they left off.

How Flutter’s Built-In State Restoration Works?

The state restoration mechanisms of Flutter are implemented into the Framework to support the user interfaces in case they are closed by the user or disrupted. This feature is useful in creating mobile applications, where users will want to navigate to further sessions without interruption. The state restoration system revolves around three key concepts:

  1. RestorationMixin:
    • It is a powerful mixin that can be implemented to any widget.
    • Auto saves a widget’s state when the app performs the background tasks or when it is closed.
    • Restores the widget’s previous state when the app is reopened without requiring complex logic for data loading.
    • Simplifies the app development, so the developers can focus on building complex features.
  2. RestorationId:
    • A unique identifier that connects a widget’s state to a particular restoration scope.
    • A widget must have a unique restoration ID to retain its state.
    • Ensures that the app must retrieve the correct state for each widget when it is restored.
    • Helps maintain multiple states across various widgets, promoting organized state management.
  3. RestorationScope:
    • Defines the environment inside which widgets provide the same restoration IDs.
    • It is crucial to group widgets that require state restoration collectively.
    • Ensures that multiple widgets on one page or feature retrieve their states from the same context.
    • Maintains consistency by grouping related states and thus improving user experience.

In conclusion, since the state restoration is already a part of the flutter framework, it utilizes RestorationMixin, RestorationId, and RestorationScope to offer a reliable and very efficient mechanism for the management of app state to further boost the usability of such applications without much demand for extra efforts from the developers.

A computer with two monitors and a keyboard showing some programming codes.

A Guide to Setting Up Basic State Restoration in Flutter

Want to implement state restoration in Flutter? It’s simple, follow the basic steps given below:

  1. Add the RestorationMixin to the widget.
  2. Implement the restoreState method, it specifies how each state should be restored.
  3. Use RestorationId to ensure each widget has a unique key that connects to its state.

Code Example: Basic Counter App with State Restoration

class RestorableCounter extends StatefulWidget {
  @override
  _RestorableCounterState createState() => _RestorableCounterState();
}
 
class _RestorableCounterState extends State<RestorableCounter> with RestorationMixin {
  final RestorableInt _counter = RestorableInt(0);
 
  @override
  String get restorationId => 'counter';
 
  @override
  void restoreState(RestorationBucket? oldBucket, bool initialRestore) {
    registerForRestoration(_counter, 'counter');
  }
 
  void _incrementCounter() {
    setState(() {
      _counter.value++;
    });
  }
 
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('State Restoration Example')),
      body: Center(
        child: Text('Counter: ${_counter.value}'),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        child: Icon(Icons.add),
      ),
    );
  }
}

In this example, the state of the counter is saved and restored across app sessions, providing a seamless experience.

Implementing Custom State Restoration in Flutter

Flutter provides various RestorableProperty types like RestorableBool, RestorableInt, and RestorableTextEditingController to support state management for built-in data types. However, for handling custom data types use RestorableCustomValue.

Code Example: Custom Restorable Data in a Complex App

For instance, if you want to save and restore the form input added by the user, simply use a restorable property to store data.

class RestorableUserFormData extends RestorableCustomValue<UserFormData> {
  RestorableUserFormData() : super(UserFormData());
 
  @override
  UserFormData fromPrimitives(Object? data) {
    final json = data as Map<String, dynamic>;
    return UserFormData.fromJson(json);
  }
 
  @override
  Object toPrimitives() {
    return value.toJson();
  }
}

In this example, the RestorableCustomValue handles a custom data type (UserFormData) that can be stored and restored using JSON.

Best Practices for Flutter State Restoration

To effectively implement state restoration, follow the best practices mentioned below for code development and design. Here are some guidelines:

  1. Use RestorationMixin Judiciously:
    • Implement the RestorationMixin only where necessary to avoid performance bottlenecks.
    • Limit its usage to widgets that handle user interactions or important states to keep restoration efficient.
  2. Organize Restoration IDs Carefully:
    • Provide unique RestorationIds for each widget within scope.
    • Carefully structure your restoration IDs in complex states, to avoid duplication and conflicts.
  3. Limit State Size:
    • Avoid restoring large or complex objects directly within the state.
    • Store references like IDs and fetch only required data asynchronously. This minimizes memory overhead and speeds up restoration.
  4. Restore Nested Widget States:
    • Ensure that state restoration covers all nested widgets in the app to maintain consistency across the entire UI.
    • Use RestorationScope to ensure the restoration of related widgets, without breaking the hierarchy.
  5. Handle Asynchronous Data Properly:
    • Check and list the widgets that are dependent on asynchronous data during state restoration.
    • Ensure data fetching occurs smoothly after state restoration is completed, by preserving placeholders or loading indicators when necessary.
  6. Test State Restoration Extensively:
    • Apply test to ensure restored states are consistent and predictable across different device states.
    • Test edge cases such as rapid app switching, backgrounding, and low-memory scenarios to ensure the system handles them well.
Two men working on computers in an office.

The Role of UI Design in State Restoration: Figma to Flutter

The user interface is the key to how users manage to view the restored state in an application. In general, the effective User Interface design aims to let users continue their activities with little confusion or interruption.

  1. UI as a Visual Guide for State Restoration:
    • UI should inform users about the app’s restored state when they resume the app state (in the same state they left).
    • Again, such components as tab panels, form controls, and navigation bars have to maintain their previous location and value states.
  2. Designing for Restoration in Figma:
    • When designing a component in Figma, progress bars, sliders, and form inputs should be considered with an eye to restoration.
    • Accompany Figma’s prototyping designs with visuals to indicate where the user was interrupted. Replicate these designs as Flutter widgets.
  3. Consistency from Figma to Flutter:
    • Ensure that the design systems in Figma match the widget-based architecture of Flutter correctly.
    • Designers pass UI mockups to developers primarily in Figma, so after restoration, the Figma elements by designers should match Flutter’s widgets after Figma to Flutter conversion.

Enhance User Experience with State Restoration

State restoration is an important tool in Flutter’s arsenal that improves the user experience by preserving states across sessions. Though Flutter’s built-in restoration system works great for simple use cases, handling complex apps requires custom solutions.

That’s where Flutter’s flexible state restoration framework and RestorableCustomValue handle the job well. With these features, developers can ensure that even the most intricate stateful widgets are preserved seamlessly.

Get ready to use it in your Flutter apps!

See the official Guide to State Restoration in Flutter, and try it on your next project. If you are looking for a good implementation of your vision into a mobile app, hire Flutter developers with the best skills. Overall, incorporating state restoration will help developers improve user experience with consumed states’ restoration and create a smooth and intuitive experience!

Disclosure: Some of our articles may contain affiliate links; this means each time you make a purchase, we get a small commission. However, the input we produce is reliable; we always handpick and review all information before publishing it on our website. We can ensure you will always get genuine as well as valuable knowledge and resources.

Share the Love

Published By: Souvik Banerjee

Souvik Banerjee Web developer and SEO specialist with 20+ years of experience in open-source web development, digital marketing, and search engine optimization. He is also the moderator of this blog "RS Web Solutions (RSWEBSOLS)".

Related Articles