[Flutter/dart] Save the state of Redux Store / How to use redux_persist
Overview
In many cases, you want to retain the data set by the user even after the application is closed. If you are using redux for state management, you can easily persist your data by using a library called redux_persist.
Method
※I will assume that flutter_redux is already installed.
Installation
First, add the following to pubsec.yaml.
dependencies:
redux_persist: ^0.8.4
Import the library at the beginning of main.dart.
(I think that it is basically used in main.dart, but if it is different, please read as appropriate)
import 'package:redux_persist/redux_persist.dart';
Preparation
The managed state is AppState. We will add the necessary processing to AppState.
Initialization processing is required when there is no data yet.
class AppState{
String item;
int number;
AppState({@required this.items, this.partners});
//Initialization processing
AppState.InitState() {
item="";
number=0;
}
}
When saving the state, convert the data to json format. Add conversion to json and read processing from json.
//convert to json
Map toJson()=>{
'item': item,
'number': number,
};
//read from json
static AppState fromJson(dynamic json){
AppState state=AppState(
item: json['item'],
number=json['number']
);
return state;
}
Save method
Here is the main issue. Add the following processing before runApp () of main.
void main() async{
//get the path of local directory
String _storage_path=await getLocalDir();
final persistor = Persistor<AppState>(
storage: FileStorage(File("${_storage_path}/state.json")),
serializer: JsonSerializer<AppState>(AppState.fromJson),
); //※1 create persistor
AppState initialState;
try{
initialState=await persistor.load();
}
catch(e){
initialState=null;
} //※2 ead data from persistor
final Store<AppState> store=Store<AppState>(
appStateReducer, //※self-made reducer
initialState: initialState?? AppState.InitState(),
middleware: [AppStateMiddleWare, persistor.createMiddleware()]
); //※3 Initialize store
runApp(MyApp(store: store,));
}
First, create a persistor instance. (* 1)
For storage:, specify the data storage destination. Here, saving to a local file is used, but it seems that it can also be saved to the web etc.
The following method is used to get the local directory.
static Future<String> getLocalDir() async {
final directory = await getApplicationDocumentsDirectory();
return directory.path;
}
For serializer :, specify the serializer of the data. Here, JsonSerializer is used and the fromJson method created earlier is specified in the decoder.
Next, read the data from the persistor (* 2). If the data has not been saved yet, fromJson will return null, so exception handling will be included. (I added the initialization process later, but you may add it with the catch statement here)
Finally, initialize the Store (* 3).
Put the state read from the persistor in initState :, and initialize the state if null is returned.
The process of saving data is done by middleware provided by redux_persistor. Specify the middleware generated by persistor.createMiddleware () in middleware:.
About middleware
・When is the data saved?
The source code of createMiddleware() is as follows.
Middleware<T> createMiddleware() {
Timer _saveTimer;
return (Store<T> store, dynamic action, NextDispatcher next) {
next(action);
if (shouldSave != null && shouldSave(store, action) != true) {
return;
}
// Save
try {
if (throttleDuration != null) {
// Only create a new timer if the last one hasn't been run.
if (_saveTimer?.isActive != true) {
_saveTimer = Timer(throttleDuration, () => save(store.state));
}
} else {
save(store.state);
}
} catch (_) {}
};
}
Since there is a save () process after next (action), the data is saved after the action (data change, etc.) (obviously).
・Want to use my own middleware
Besides saving data, there are other things you want middleware to do. If you also want to use your own middleware that describes such processing, you can put them together in a List and pass them to middleware:.
The middleware processing is executed in order from the beginning of the List, and the next middleware is executed by next (). The next of the last middleware is action. If the order of processing is important, pay attention to the order of List and the position of next.
Lastly
Actually, at first I saved the data in shared_preference without knowing redux_persistor, but with redux_persist it is quite easy to save the data. It's important to find out ...
Recent Posts
See AllWhat want to do I want to create an input form using TextField. For example, if the input content is a monetary amount, I would like to...
What want to do There is a variable that remain unchanged once the initial value is determined. However, it cannot be determined yet when...
What want to do As the title suggests. Place two widgets in one line on the screen One in the center of the screen and the other on the...
Comments