Flutter异步状态管理插件redux_future_middleware的使用
Flutter 异步状态管理插件 redux_future_middleware 的使用
简介
Redux Future Middleware 是一个用于处理 Dart Futures 的 Redux 中间件包。通过创建一个 FutureAction
,该中间件可以拦截并处理异步操作。
使用步骤
-
创建 AppState
AppState
类用于存储应用程序的当前状态。class AppState { String value; String loadingValue; }
-
定义 Action 定义一个独特的 Action 来标识每个
FutureAction
。class ExampleAction {}
-
创建 Reducer 创建一个 Reducer 来处理未来的动作。
AppState exampleReducer(AppState prevState, dynamic action) { if (action is FuturePendingAction<ExampleAction>) { return prevState..loadingValue = 'Fetching'; } else if (action is FutureSucceededAction<ExampleAction, String>) { return prevState..value = action.payload..loadingValue = 'Done'; } else if (action is FutureFailedAction<ExampleAction>) { return prevState..loadingValue = 'Failed'; } return prevState; }
-
创建 Store 创建一个包含
futureMiddleware
的 Store。它将拦截所有被分发的FutureAction
。final store = Store<AppState>( exampleReducer, middleware: [futureMiddleware], );
-
分发 FutureAction 分发一个
FutureAction
进行拦截。store.dispatch(FutureAction<ExampleAction, String>( future: Future.value('Hi'), ));
简化 Reducer 逻辑
该库现在附带了一个 FutureReducer
工具,可以帮助减少在创建处理 FuturePendingAction
和 FutureFailedAction
的 Reducer 时所需的冗余逻辑。
内置默认值
使用内置默认值,上述示例可以简化为:
class AppState extends BaseState<AppState> {
String value;
}
FutureReducer<AppState, ExampleAction, String> exampleReducer =
FutureReducer<AppState, ExampleAction, String>(
successReducer: successReducer,
);
其中 BaseState
类扩展了 FutureState
类,并实现了一些默认行为。
class BaseState extends FutureState<BaseState> {
String loadingValue;
[@override](/user/override)
BaseState updateOnFailed(FutureFailedAction action) => this
..loadingValue = "Failed";
[@override](/user/override)
BaseState updateOnPending(FuturePendingAction action) => this
..loadingValue = "Fetching";
}
自定义默认值
如果您不想使用 FutureState
和内置默认值,可以设置自己的默认 pendingReducer
和 failedReducer
。
FutureReducer<AppState, ExampleAction, String> exampleReducer =
FutureReducer<AppState, ExampleAction, String>(
successReducer: successReducer,
pendingReducer: pendingReducer,
failedReducer: failedReducer,
);
完整示例
以下是一个完整的示例代码,展示了如何使用 redux_future_middleware
。
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:redux/redux.dart';
import 'package:redux_future_middleware/redux_future_middleware.dart';
// 定义 AppState
class AppState {
String value;
String loadingValue;
AppState(this.value, this.loadingValue);
AppState copyWith({String? value, String? loadingValue}) {
return AppState(value ?? this.value, loadingValue ?? this.loadingValue);
}
}
// 定义 Action
class ExampleAction {}
// 定义 Reducer
AppState exampleReducer(AppState prevState, dynamic action) {
if (action is FuturePendingAction<ExampleAction>) {
return prevState.copyWith(loadingValue: 'Fetching');
} else if (action is FutureSucceededAction<ExampleAction, String>) {
return prevState.copyWith(value: action.payload, loadingValue: 'Done');
} else if (action is FutureFailedAction<ExampleAction>) {
return prevState.copyWith(loadingValue: 'Failed');
}
return prevState;
}
void main() {
final store = Store<AppState>(
exampleReducer,
initialState: AppState('', ''),
middleware: [futureMiddleware],
);
runApp(MyApp(store: store));
}
class MyApp extends StatelessWidget {
final Store<AppState> store;
MyApp({required this.store});
[@override](/user/override)
Widget build(BuildContext context) {
return StoreProvider<AppState>(
store: store,
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
),
);
}
}
class MyHomePage extends StatelessWidget {
final String? title;
MyHomePage({this.title});
[@override](/user/override)
Widget build(BuildContext context) {
return StoreConnector<AppState, AppState>(
converter: (store) => store.state,
builder: (context, state) {
return Scaffold(
appBar: AppBar(
title: Text(title!),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Loading Value:',
),
Text(
state.loadingValue,
style: Theme.of(context).textTheme.headline4,
),
Text(
'Value:',
),
Text(
state.value,
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
store.dispatch(FutureAction<ExampleAction, String>(
future: Future.value('Hello World'),
));
},
tooltip: 'Fetch Data',
child: Icon(Icons.refresh),
),
);
},
);
}
}
更多关于Flutter异步状态管理插件redux_future_middleware的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter异步状态管理插件redux_future_middleware的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter中使用redux_future_middleware
进行异步状态管理的代码示例。redux_future_middleware
是一个中间件,它允许你将 Future 操作与 Redux 状态管理结合起来,从而更容易地处理异步任务的状态(如加载中、成功、失败)。
首先,确保你的pubspec.yaml
文件中包含以下依赖项:
dependencies:
flutter:
sdk: flutter
flutter_redux: ^0.6.0 # 或者最新版本
redux: ^4.0.0 # 或者最新版本
redux_future_middleware: ^0.4.0 # 或者最新版本
然后,运行flutter pub get
来安装这些依赖。
接下来,我们创建一个简单的Flutter应用,演示如何使用redux_future_middleware
。
1. 创建Action和Action Creator
import 'package:redux/redux.dart';
import 'package:redux_future_middleware/redux_future_middleware.dart';
// 定义Action类型
enum AppActionTypes { loadDataRequest, loadDataSuccess, loadDataFailure }
// 定义Action
class LoadDataRequestAction {}
class LoadDataSuccessAction {
final List<String> data;
LoadDataSuccessAction(this.data);
}
class LoadDataFailureAction {
final String error;
LoadDataFailureAction(this.error);
}
// Action Creator
Future<dynamic> loadDataRequest() async {
return FutureActionCreator(
AppActionTypes.loadDataRequest,
() async {
// 模拟一个异步操作,例如从网络获取数据
await Future.delayed(Duration(seconds: 2));
try {
final data = List<String>.generate(10, (i) => "Item $i");
return LoadDataSuccessAction(data);
} catch (e) {
return LoadDataFailureAction(e.toString());
}
},
)();
}
2. 创建Reducer
import 'package:redux/redux.dart';
import 'package:redux_future_middleware/redux_future_middleware.dart';
import 'package:meta/meta.dart';
// 定义AppState
class AppState {
final List<String> data;
final FutureStatus<Null> loadDataStatus;
AppState({
@required this.data,
@required this.loadDataStatus,
});
factory AppState.initial() {
return AppState(
data: [],
loadDataStatus: FutureStatus.pending(),
);
}
AppState copyWith({
List<String> data,
FutureStatus<Null> loadDataStatus,
}) {
return AppState(
data: data ?? this.data,
loadDataStatus: loadDataStatus ?? this.loadDataStatus,
);
}
}
// 创建Reducer
Reducer<AppState> appReducer = combineReducers<AppState>([
TypedReducer<AppState, FutureAction<Null>>(_handleLoadData, AppActionTypes.loadDataRequest),
TypedReducer<AppState, LoadDataSuccessAction>(_handleLoadDataSuccess),
TypedReducer<AppState, LoadDataFailureAction>(_handleLoadDataFailure),
]);
AppState _handleLoadData(AppState state, action) {
return state.copyWith(loadDataStatus: action.status);
}
AppState _handleLoadDataSuccess(AppState state, LoadDataSuccessAction action) {
return state.copyWith(
data: action.data,
loadDataStatus: FutureStatus.completed(),
);
}
AppState _handleLoadDataFailure(AppState state, LoadDataFailureAction action) {
return state.copyWith(
loadDataStatus: FutureStatus.rejected(action.error),
);
}
3. 设置Store
import 'package:flutter_redux/flutter_redux.dart';
import 'package:redux/redux.dart';
import 'package:redux_future_middleware/redux_future_middleware.dart';
void main() {
final store = Store<AppState>(
appReducer,
initialState: AppState.initial(),
middleware: [createFutureMiddleware()],
);
runApp(StoreProvider<AppState>(
store: store,
child: MyApp(),
));
}
4. 在UI中使用Store
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:redux/redux.dart';
import 'package:redux_future_middleware/redux_future_middleware.dart';
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Redux Future Middleware Demo')),
body: Center(
child: StoreConnector<AppState, _ViewModel>(
converter: (store) => _ViewModel.fromStore(store),
builder: (_, vm) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
if (vm.isLoading) CircularProgressIndicator(),
if (vm.hasError) Text('Error: ${vm.error}'),
if (vm.data.isNotEmpty) Text('Data: ${vm.data.join(", ")}'),
ElevatedButton(
onPressed: vm.loadData,
child: Text('Load Data'),
),
],
);
},
),
),
),
);
}
}
class _ViewModel {
final List<String> data;
final bool isLoading;
final String error;
final Function loadData;
_ViewModel({
this.data,
this.isLoading,
this.error,
this.loadData,
});
factory _ViewModel.fromStore(Store<AppState> store) {
return _ViewModel(
data: store.state.data,
isLoading: store.state.loadDataStatus.isPending,
error: store.state.loadDataStatus.maybeMap(
rejected: (e) => e.error,
orElse: () => null,
),
loadData: () => store.dispatch(loadDataRequest()),
);
}
}
这个示例演示了如何使用redux_future_middleware
来处理异步操作的状态管理。我们通过FutureActionCreator
来创建一个异步操作,并使用FutureStatus
来跟踪这个操作的状态。Reducer根据操作的状态来更新应用的状态,而UI则根据最新的状态来渲染相应的组件。