State Management

FlutterFlow handles state management in several ways, depending on the scope.

In general, state is managed with the Provider package, which handles provision of data models of components, pages and app state.

Page & Component Models

In FlutterFlow, both component widget models and page models share a uniform structure, enhancing consistency across the framework. They include local state fields to hold data specific to the component, like sizes or user inputs. These models also have initialization and disposal methods: initState for setting things up when the widget starts, and dispose for cleaning up resources when the widget is done.

Additionally, they provide space for action blocks, which are a set of actions that performs a specific task and can be reused in different parts of the app, and helper methods for extra functionalities needed by the component. This uniform structure across models aids in efficiently managing the state and interactions of various components in the app.

Page State

Any variable used within the page only (like a text field validator, or the value of a checkbox) is stored in the Model of each page. Variables can be accessed by other component children in the same page - for example, on a page with a form, a button tap action in one component may need to access the value of a text field in a different component.

Variables within a page are tracked via StatefulWidgets, encapsulated into that page’s Model.

Component State

Similar to page state, component variables are accessible within the component they are defined in. Each defined component has a Model and Widget class. Variables may be passed in from their parent as parameters. However, you can also access component state values from its parent Page widget.

This is because the Model of a component is instantiated within the parent Page model. It makes use of the Provider method context.read(), which will return any existing model in the tree before instantiating a new one. So, any updates to state in the component model will reflect in the parent’s instance of the component model.

One of the helper methods in flutter_flow_model.dart is wrapWithModel(). It’s a method that wraps the child in a Provided model, to make it accessible to the child, and also sets a callback function which is generally used to call setState() in the parent page and update any values that changed. We use this wrapper around widgets that need to access the data included in the model.

For example, if a page has a component which includes a text field, and later in the page we have a button which needs to access the value of that text field, the button would be wrapped with wrapWithModel() and include the text field component’s Model as a parameter.

One thing to note is that components can’t directly access variables of other components in the same page; however, you can pass a variable from ComponentA as a parameter of ComponentB in their parent Page; that way, B gets all the A updates as you would expect.

App State

Variables that need to be used throughout the app, like a username displayed on multiple pages, can be added to App State. See lib/app_state.dart.

All defined app state variables are part of the FFAppState class, which is a ChangeNotifier - that is, listeners can subscribe to it and be notified when changes to it happen.

In each page that needs access to app state variables, we call context.watch<FFAppState>(), which initializes the listener for that page. The watch() method comes from the Provider package, a useful wrapper for accessing inherited widgets.

Persisting App State

When an app state variable is created, if the "Persisted" option is checked, FlutterFlow uses the shared_preferences package to save it to the device, so it will be available after the app restarts. Useful for persisting a login, or a light/dark mode user choice.

If "Secure Persisted Fields" is selected in app state settings, FlutterFlow uses the flutter_secure_storage package to encrypt the value. This uses the platform specific implementations of Keychain for iOS, KeyStore for Android, and libsecret for Linux.

Global State

Global state variables are accessible bits of information that relate to the device:

  • Screen size

  • Platform - mobile, web, Android, iOS

  • Is Keyboard visible

  • Current time

They’re accessible from the "Global Properties" section, and are available to every FlutterFlow app. This particular state is not user generated and are automatically added by FlutterFlow. Users can leverage App State variables for their global usecases.

Global properties are fetched via methods defined in flutter_flow_utils.dart and generally use built-in Flutter libraries like dart:io to fetch their information.

Constants

For values that remain constant throughout the app, such as API keys or environment flags, we use the FFAppConstants class. See lib/app_constants.dart. This class is an abstract one, meaning it can't be instantiated but serves as a namespace for static constants.

Last updated