FFAppState
This guide uses example of the generated code of the EcommerceFlow demo app. To view the generated code directly, check out the Github repository.
The FFAppState
class in FlutterFlow acts as a central hub for managing the application's global state. It's designed as a singleton, meaning there's only one instance of this class throughout the app's lifecycle. This class extends ChangeNotifier, allowing widgets to listen and react to state changes.
It includes methods for initializing and updating the app's persisted state and also defines various state variables with corresponding getters and setters for manipulating these values.
Here is a basic template of the class, taken from the eCommerceFlow demo app's generated code:
class FFAppState extends ChangeNotifier {
static FFAppState _instance = FFAppState._internal();
factory FFAppState() {
return _instance;
}
FFAppState._internal();
static void reset() {
_instance = FFAppState._internal();
}
void update(VoidCallback callback) {
callback();
notifyListeners();
}
// App State variable of primitive type with a getter and setter
bool _enableDarkMode = false;
bool get enableDarkMode => _enableDarkMode;
set enableDarkMode(bool value) {
_enableDarkMode = value;
}
}
The _enableDarkMode
is an App State variable created by developer that creates its own corresponding getter and setter.
Updating FFAppState
When updating the FFAppState from the Action Flow Editor, you will be presented with several update type options such as Rebuild All Pages, Rebuild Current Page, and No Rebuild. Let's see how the generated code changes when these options are selected.
Rebuild Current Page
When a developer chooses to update App State with the update type set to Rebuild Current Page, the corresponding setter
is called. Immediately after, setState((){});
is invoked, which updates only the current page.
Here's an example of the generated code when we update the App State enableDarkMode
in the onInitialization
action trigger of the ProductListPage
.
SchedulerBinding.instance.addPostFrameCallback((_) async {
FFAppState().enableDarkMode = !(FFAppState().enableDarkMode ?? true);
setState(() {});
});
Rebuild All Pages
In this case, the update type is set to Rebuild All Pages, meaning that the setter
is called, followed by the update()
method. This method internally calls notifyListeners()
, which is crucial for updating any widgets that depend on this variable.
SchedulerBinding.instance.addPostFrameCallback((_) async {
FFAppState().enableDarkMode = !(FFAppState().enableDarkMode ?? true);
FFAppState().update(() {});
});
When updating App State variables from custom code, such as Custom Actions, it's crucial to call the update function to ensure that the changes are reflected across all pages. For example, you should use:
FFAppState().update(() => FFAppState().enableDarkMode = !(FFAppState().enableDarkMode ?? true));
No Rebuild
Only the setter is called with no setState or update method invoked afterward. This means that only the variable is updated, with no state changes occurring after the data update.
watch<FFAppState>
When you add an Update App State action via the Action Flow Editor, the corresponding pages will include this line within the build method:
@override
Widget build(BuildContext context) {
context.watch<FFAppState>();
...
By using context.watch<FFAppState>()
, the widget effectively subscribes to any changes in the FFAppState
class. Whenever there's a change in the FFAppState
object, this widget automatically rebuilds to reflect those changes. This ensures that your widget always displays the most current data and state of the app, maintaining an up-to-date and responsive user interface.
Managing AppState<List>
When you add an App State variable of List
type in FlutterFlow, several utility functions are automatically generated to help you manage this list. These functions include a getter, a setter, and methods for adding, removing, and updating items in the list. This setup ensures that you can easily interact with the list while keeping the app state consistent and responsive. Below is an explanation of these generated functions using the specific example of a LatLngList.
late LoggableList<LatLng> _LatLngList =
LoggableList([LatLng(37.4071594, -122.0775312), LatLng(40.7358633, -73.9910835)]);
List<LatLng> get LatLngList => _LatLngList?..logger = () => debugLogAppState(this);
set LatLngList(List<LatLng> value) {
if (value != null) {
_LatLngList = LoggableList(value);
}
debugLogAppState(this);
}
void addToLatLngList(LatLng value) {
LatLngList.add(value);
}
void removeFromLatLngList(LatLng value) {
LatLngList.remove(value);
}
void removeAtIndexFromLatLngList(int index) {
LatLngList.removeAt(index);
}
void updateLatLngListAtIndex(
int index,
LatLng Function(LatLng) updateFn,
) {
LatLngList[index] = updateFn(_LatLngList[index]);
}
void insertAtIndexInLatLngList(int index, LatLng value) {
LatLngList.insert(index, value);
}
These functions are automatically generated to provide a convenient and consistent way to manage list-type App State variables, making it easier to maintain the app's state:
- The list
LatLngList
is initialized as a private variable_LatLngList
of typeLoggableList
, which helps in managing the list with additional logging capabilities. - The get
LatLngList
method allows other parts of the app to access theLatLngList
. - The set
LatLngList
method allows you to replace the entireLatLngList
with a new one. When a new list is assigned, it updates the private variable_LatLngList
and logs this change usingdebugLogAppState
. - The
addToLatLngList
function appends a newLatLng
object to the LatLngList, dynamically updating the list as the app runs. - The
removeFromLatLngList
function removes a specificLatLng
object from theLatLngList
, ensuring the list remains accurate and up-to-date. - The
removeAtIndexFromLatLngList
function removes aLatLng
object from the list based on its index position. - The
updateLatLngListAtIndex
function allows you to update aLatLng
object at a specific index by applying an update function (updateFn
) to it. - The
insertAtIndexInLatLngList
function inserts a newLatLng
object into theLatLngList
at a specific index, shifting the existing items as necessary.
To learn more about creating and using App State variables in FlutterFlow's UI, check out the App State guide.