# Redux persist

最基本的redux counter:

class AppState {
  final int counter;

  AppState({this.counter = 0});

  AppState copyWith({int counter}) =>
      AppState(counter: counter ?? this.counter);
}

class Action {}

class IncrementCounterAction extends Action {}

AppState reducer(AppState state, dynamic action) {
  if (action is IncrementCounterAction) {
    // Increment
    return state.copyWith(counter: state.counter + 1);
  }

  return state;
}

void main() {
  // Create your store as a final variable in the main function or inside a
  // State object. This works better with Hot Reload than creating it directly
  // in the `build` function.
  final store = Store<AppState>(
    reducer,
    initialState: AppState(),
    middleware: [],
  );

  runApp(FlutterReduxApp(
    title: 'Flutter Redux Demo',
    store: store,
  ));
}

class FlutterReduxApp extends StatelessWidget {
  final Store<AppState> store;
  final String title;

  FlutterReduxApp({Key key, this.store, this.title}) : super(key: key);

  
  Widget build(BuildContext context) {
    // The StoreProvider should wrap your MaterialApp or WidgetsApp. This will
    // ensure all routes have access to the store.
    return StoreProvider<AppState>(
      // Pass the store to the StoreProvider. Any ancestor `StoreConnector`
      // Widgets will find and use this value as the `Store`.
      store: store,
      child: MaterialApp(
        theme: ThemeData.dark(),
        title: title,
        home: Scaffold(
          appBar: AppBar(
            title: Text(title),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text(
                  'You have pushed the button this many times:',
                ),
                StoreConnector<AppState, String>(
                  converter: (store) => store.state.counter.toString(),
                  builder: (context, count) {
                    return Text(
                      count,
                      style: Theme.of(context).textTheme.display1,
                    );
                  },
                )
              ],
            ),
          ),
          floatingActionButton: StoreConnector<AppState, VoidCallback>(
            converter: (store) {
              // Return a `VoidCallback`, which is a fancy name for a function
              // with no parameters. It only dispatches an Increment action.
              return () => store.dispatch(IncrementCounterAction());
            },
            builder: (context, callback) {
              return FloatingActionButton(
                // Attach the `callback` to the `onPressed` attribute
                onPressed: callback,
                tooltip: 'asdasdasd',
                child: Icon(Icons.add),
              );
            },
          ),
        ),
      ),
    );
  }
}

telegram-cloud-photo-size-5-6273879370783369515-y

這個Apps 的AppState只有一個

final int counter;

現嘗試使用redux_persist (opens new window)將state 轉換成json,最後以file的形式儲存在本地.

先加入redux_persistredux_persist_flutter

  ...
  dependencies:
  flutter:
    sdk: flutter
  
  redux_persist: ^0.8.3					//Add
  redux_persist_flutter: ^0.8.2 //Add
  ...

由於是以json的方式儲存,所以要將AppState轉換成json

class AppState {
  final int counter;

  AppState({this.counter = 0});

  AppState copyWith({int counter}) =>
      AppState(counter: counter ?? this.counter);
      
  //Add
  static AppState fromJson(dynamic json) =>
    AppState(counter: json != null ? json["counter"] as int : 0);
	//Add
  dynamic toJson() => {'counter': counter};
}

在官方教學中的example (opens new window) 沒有做第一次的null處理

FIX: Throw an exception on first startup. (opens new window)

最後在main()使用

import 'package:redux_persist/redux_persist.dart';
import 'package:redux_persist_flutter/redux_persist_flutter.dart';

void main() async { // modify to async
  
  // since main() is async, https://stackoverflow.com/a/57775690/5588637
  WidgetsFlutterBinding.ensureInitialized();

  // Create Persistor
  final persistor = Persistor<AppState>(
    storage: FlutterStorage(),
    serializer: JsonSerializer<AppState>(AppState.fromJson),
  );

  // Load initial state
  final initialState = await persistor.load();

  final store = Store<AppState>(
    reducer,
    initialState: initialState ?? AppState(),
    // Add Persistor Middleware to handle load and save data
    middleware: [persistor.createMiddleware()],
  );

  runApp(FlutterReduxApp(
    title: 'Flutter Redux Demo',
    store: store,
  ));
}

每一次State有變動時,會在Middleware層轉換成json後儲存在本地file中, 重新開apps時會先在file中load data去State,如果沒有的話才按正常步驟進行。

參考Path:

Android Path iOS Path
/data/data/Application ID/app_flutter/persist_app.json /Users/{username}/Library/Developer/CoreSimulator/Devices/Devices Identifier/Data/Application/Application Identifier/Documents/persist_app.json
//persist_app.json
{
	"counter":20
}

預設是使用documentFile,可以選擇用sharedPreferences

更多用法可以查看 redux_persist (opens new window)redux_persist_flutter (opens new window)

Source code (opens new window)

Last Updated: Sat Jun 06 2020 00:43:46 GMT+0000
贊助商連結
(adsbygoogle = window.adsbygoogle || []).push({});