在移動(dòng)端的開發(fā)中我們?nèi)绾潍@取用戶是否登錄呢,一般我們最常用的做法是在用戶登錄后將獲取的token存在本地然后在用戶下次登錄的時(shí)候我們從本地讀取這個(gè)token如果有那么我們判斷用戶之前登錄過,如果沒有我們就知道用戶沒有登錄.但是在接觸了redux以后發(fā)現(xiàn)redux有自己的數(shù)據(jù)持久化Redux Persist.那今天簡(jiǎn)單研究一下我們?nèi)绾问褂肦edux Persist進(jìn)行狀態(tài)的管理
首先我們就是想儲(chǔ)存一些我們已經(jīng)獲取的數(shù)據(jù)這個(gè)時(shí)候redux_persist_flutter給我們提供了一個(gè)關(guān)鍵的類Persistor,那我們點(diǎn)進(jìn)去看看這個(gè)Persistor到底是個(gè)什么
class Persistor<T> {
/// Storage engine to save/load from/to.
final StorageEngine storage;
/// Transformations on state to be applied on save/load.
final Transforms<T> transforms;
/// Transformations on raw data to be applied on save/load.
final RawTransforms rawTransforms;
/// State serialized used to serialize the state to/from bytes.
final StateSerializer<T> serializer;
/// Debug mode (prints debug information).
bool debug;
/// Duration for which to throttle saving. Disable by setting to null.
/// It is recommended to set a duration of a few (2-5) seconds to reduce
/// storage calls, while preventing data loss.
/// A duration of zero (default) will try to save on next available cycle
Duration throttleDuration;
/// Synchronization lock for saving
final _saveLock = Lock();
/// Function that if not null, returns if an action should trigger a save.
final bool Function(Store<T> store, dynamic action) shouldSave;
Persistor({
@required this.storage,
@required this.serializer,
this.transforms,
this.rawTransforms,
this.debug = false,
this.throttleDuration = Duration.zero,
this.shouldSave,
});
/// Middleware used for Redux which saves on each action.
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 (_) {}
};
}
/// Load state from storage
Future<T> load() async {
try {
_printDebug('Starting load...');
_printDebug('Loading from storage');
// Load from storage
Uint8List data;
try {
data = await storage.load();
} catch (error) {
throw StorageException('On load: ${error.toString()}');
}
_printDebug('Running load raw transformations');
try {
// Run all raw load transforms
rawTransforms?.onLoad?.forEach((transform) {
data = transform(data);
});
} catch (error) {
throw TransformationException(
'On load raw transformation: ${error.toString()}',
);
}
_printDebug('Deserializing');
T state;
try {
state = serializer.decode(data);
} catch (error) {
throw SerializationException('On load: ${error.toString()}');
}
_printDebug('Running load transformations');
try {
// Run all load transforms
transforms?.onLoad?.forEach((transform) {
state = transform(state);
});
} catch (error) {
throw TransformationException(
'On load transformation: ${error.toString()}',
);
}
_printDebug('Done loading!');
return state;
} catch (error) {
_printDebug('Error while loading: ${error.toString()}');
rethrow;
}
}
/// Save state to storage.
Future<void> save(T state) async {
try {
_printDebug('Starting save...');
_printDebug('Running save transformations');
// Run all save transforms
try {
transforms?.onSave?.forEach((transform) {
state = transform(state);
});
} catch (error) {
throw TransformationException(
"On save transformation: ${error.toString()}",
);
}
_printDebug('Serializing');
var data = serializer.encode(state);
_printDebug('Running save raw transformations');
try {
// Run all raw save transforms
rawTransforms?.onSave?.forEach((transform) {
data = transform(data);
});
} catch (error) {
throw TransformationException(
'On save raw transformation: ${error.toString()}');
}
_printDebug('Saving to storage');
// Save to storage
try {
// Use lock to prevent writing twice at the same time
await _saveLock.synchronized(() async => await storage.save(data));
} catch (error) {
throw StorageException('On save: ${error.toString()}');
}
_printDebug('Done saving!');
} catch (error) {
_printDebug('Error while saving: ${error.toString()}');
rethrow;
}
}
void _printDebug(Object object) {
if (debug) {
print('Persistor debug: $object');
}
}
}
我們看幾個(gè)重要的屬性一個(gè)是storage
final persistor = Persistor<AppState>(
storage: FlutterStorage(),
serializer: JsonSerializer<AppState>(AppState.fromJson),
);
官方實(shí)例中給出了一個(gè)FlutterStorage,繼續(xù)點(diǎn)擊看一下這是個(gè)什么東西
class FlutterStorage implements StorageEngine {
StorageEngine _locationEngine;
FlutterStorage({
String key = "app",
FlutterSaveLocation location = FlutterSaveLocation.documentFile,
}) {
switch (location) {
case FlutterSaveLocation.documentFile:
_locationEngine = DocumentFileEngine(key);
break;
case FlutterSaveLocation.sharedPreferences:
_locationEngine = SharedPreferencesEngine(key);
break;
default:
throw StorageException("No Flutter storage location");
}
}
看到了其實(shí)就是讓我們方便設(shè)置保存的位置,默認(rèn)是FlutterSaveLocation.documentFile我們也可以設(shè)置成 FlutterSaveLocation.sharedPreferences
好看第二個(gè)serializer這里就不在粘貼源碼了,有興趣的朋友可以點(diǎn)進(jìn)去看一下就是我們儲(chǔ)存數(shù)據(jù)的格式我們可以使用JsonSerializer這個(gè)時(shí)候我們要在狀態(tài)類里提供兩個(gè)方法吧我們想要保存的數(shù)據(jù)json化
class CountState{
int _count;
get count => _count;
CountState(this._count);
CountState.initState() : _count = 0;
static CountState fromJson(dynamic json) => json != null ? CountState(json['count'] as int) : CountState(0);
dynamic toJson() => {'count': _count};
}
然后我們提供一個(gè)方法用他來保存狀態(tài)
Future<Store<CountState>> InitializeStore() async {
final persistor = Persistor<CountState>(
throttleDuration: Duration(seconds: 5),
//debug: true,
storage: FlutterStorage(),
serializer:
JsonSerializer<CountState>(CountState.fromJson), // Or use other serializers
);
// 從 persistor 中加載上一次存儲(chǔ)的狀態(tài)
final initialState = await persistor.load();
final store = Store<CountState>(
reducer,
initialState: initialState ?? CountState(0),
middleware: [persistor.createMiddleware()]
);
return store;
}
然后我們?cè)趓unApp的頭上調(diào)用我們定義的方法
Store< CountState > store = await InitializeStore();
這樣就可以保存我們的狀態(tài)了
寫在最后
因?yàn)槭且苿?dòng)端出身,很多理解不是很到位,歡迎指正.