Flutter Redux中间件插件typed_redux_epics的使用
Flutter Redux中间件插件typed_redux_epics的使用
简介
typed_redux_epics
是 dart_redux_epics
的类型安全版本。它允许你在 Redux 应用程序中使用 Epic 中间件来处理异步操作,并且提供了更好的类型支持。
感谢原作者的灵感!
使用示例
以下是一个完整的示例,展示如何在 Flutter 中使用 typed_redux_epics
插件。
1. 添加依赖
首先,在你的 pubspec.yaml
文件中添加 typed_redux_epics
依赖:
dependencies:
flutter:
sdk: flutter
redux: ^6.0.0
typed_redux: ^2.0.0
typed_redux_epics: ^2.0.0
然后运行 flutter pub get
安装依赖。
2. 创建 Action 和 State
定义你的 Redux Action 和 State 类型。例如:
// actions.dart
enum TodoActionType { ADD_TODO, REMOVE_TODO }
class AddTodoAction {
final String text;
AddTodoAction(this.text);
}
class RemoveTodoAction {
final int id;
RemoveTodoAction(this.id);
}
3. 创建 Epic
Epic 是一个函数,接收 Actions 并返回一个新的 Stream 或 Iterable。
// epics.dart
import 'dart:async';
import 'package:redux/redux.dart';
import 'package:typed_redux_epics/typed_redux_epics.dart';
Future<Stream<dynamic>> fetchTodos(EpicStore store, dynamic action, NextDispatcher next) async {
// 模拟异步操作
await Future.delayed(Duration(seconds: 2));
if (action is AddTodoAction) {
return Stream.value(AddTodoAction(action.text + " (Fetched)"));
}
return Stream.empty();
}
final todoEpic = TypedEpic<dynamic, dynamic>(fetchTodos);
4. 配置 Store
将 Epic 注册到 Redux Store 中。
// store.dart
import 'package:flutter/material.dart';
import 'package:redux/redux.dart';
import 'package:typed_redux_epics/typed_redux_epics.dart';
import 'actions.dart';
import 'epics.dart';
import 'reducers.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return StoreProvider(
store: _createStore(),
child: MaterialApp(
title: 'Typed Redux Epics Example',
home: MyHomePage(),
),
);
}
Store<AppState> _createStore() {
final todoEpic = TypedEpic<dynamic, dynamic>(fetchTodos);
return Store<AppState>(
appReducer,
initialState: AppState.initial(),
middleware: [
TypedMiddleware<dynamic, dynamic>(todoEpic),
],
);
}
}
5. 编写 Reducer
Reducer 负责处理 Action 并更新 State。
// reducers.dart
import 'package:redux/redux.dart';
import 'actions.dart';
class AppState {
final List<String> todos;
AppState({required this.todos});
factory AppState.initial() => AppState(todos: []);
AppState copyWith({List<String>? todos}) =>
AppState(todos: todos ?? this.todos);
}
AppState appReducer(AppState state, dynamic action) {
if (action is AddTodoAction) {
return state.copyWith(todos: [...state.todos, action.text]);
} else if (action is RemoveTodoAction) {
return state.copyWith(todos: state.todos.where((t) => t != action.id).toList());
}
return state;
}
6. 显示 UI
创建一个简单的 UI 来显示 Todos 列表。
// my_home_page.dart
import 'package:flutter/material.dart';
import 'package:redux/redux.dart';
import 'package:example/actions.dart'; // 替换为实际路径
import 'package:example/store.dart'; // 替换为实际路径
class MyHomePage extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return StoreConnector<AppState, _ViewModel>(
converter: _ViewModel.fromStore,
builder: (context, vm) {
return Scaffold(
appBar: AppBar(title: Text('Typed Redux Epics Example')),
body: ListView.builder(
itemCount: vm.todos.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(vm.todos[index]),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () => vm.removeTodo(index),
),
);
},
),
floatingActionButton: FloatingActionButton(
onPressed: () => vm.addTodo("New Todo"),
child: Icon(Icons.add),
),
);
},
);
}
}
class _ViewModel {
final List<String> todos;
final Function(int) removeTodo;
final Function(String) addTodo;
_ViewModel({
required this.todos,
required this.removeTodo,
required this.addTodo,
});
static _ViewModel fromStore(Store<AppState> store) {
return _ViewModel(
todos: store.state.todos,
removeTodo: (index) => store.dispatch(RemoveTodoAction(index)),
addTodo: (text) => store.dispatch(AddTodoAction(text)),
);
}
}
更多关于Flutter Redux中间件插件typed_redux_epics的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter Redux中间件插件typed_redux_epics的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
typed_redux_epics
是一个用于 Flutter 和 Dart 的 Redux 中间件插件,它允许你使用 Epics
来处理异步操作。Epics
是一种基于流的中间件,通常用于处理复杂的异步逻辑,例如 API 调用、定时任务等。
安装
首先,你需要在 pubspec.yaml
文件中添加 typed_redux_epics
依赖:
dependencies:
flutter:
sdk: flutter
redux: ^5.0.0
typed_redux_epics: ^0.2.1
然后运行 flutter pub get
来安装依赖。
基本使用
1. 定义 Actions
首先,定义你的 Redux actions:
class FetchDataAction {}
class DataFetchedAction {
final List<String> data;
DataFetchedAction(this.data);
}
class FetchDataErrorAction {
final String error;
FetchDataErrorAction(this.error);
}
2. 定义 Reducer
接下来,定义你的 Reducer 来处理这些 actions:
AppState appReducer(AppState state, dynamic action) {
if (action is DataFetchedAction) {
return state.copyWith(data: action.data, isLoading: false);
} else if (action is FetchDataErrorAction) {
return state.copyWith(error: action.error, isLoading: false);
} else if (action is FetchDataAction) {
return state.copyWith(isLoading: true);
}
return state;
}
3. 定义 Epic
Epic 是一个函数,它接收一个 Stream<Action>
并返回一个 Stream<Action>
。你可以使用 typed_redux_epics
来处理异步操作:
import 'package:typed_redux_epics/typed_redux_epics.dart';
import 'package:redux/redux.dart';
import 'package:rxdart/rxdart.dart';
Stream<dynamic> fetchDataEpic(Stream<dynamic> actions, EpicStore<AppState> store) {
return actions
.whereType<FetchDataAction>()
.asyncMap((action) async {
try {
// 模拟 API 调用
await Future.delayed(Duration(seconds: 2));
return DataFetchedAction(['Item 1', 'Item 2', 'Item 3']);
} catch (e) {
return FetchDataErrorAction(e.toString());
}
});
}
4. 创建 Store
在创建 Redux store 时,将 Epic 中间件添加到 store 中:
import 'package:redux/redux.dart';
import 'package:typed_redux_epics/typed_redux_epics.dart';
final epicMiddleware = EpicMiddleware<AppState>(fetchDataEpic);
final store = Store<AppState>(
appReducer,
initialState: AppState.initial(),
middleware: [epicMiddleware],
);
5. 在 Flutter 中使用 Store
最后,你可以在 Flutter 中使用 StoreProvider
和 StoreConnector
来连接 Redux store:
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:redux/redux.dart';
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return StoreProvider(
store: store,
child: MaterialApp(
home: MyHomePage(),
),
);
}
}
class MyHomePage extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Redux Epic Example'),
),
body: StoreConnector<AppState, ViewModel>(
converter: (Store<AppState> store) => ViewModel.create(store),
builder: (context, vm) {
if (vm.isLoading) {
return Center(child: CircularProgressIndicator());
} else if (vm.error != null) {
return Center(child: Text('Error: ${vm.error}'));
} else {
return ListView(
children: vm.data.map((item) => ListTile(title: Text(item))).toList(),
);
}
},
),
floatingActionButton: FloatingActionButton(
onPressed: () {
store.dispatch(FetchDataAction());
},
child: Icon(Icons.refresh),
),
);
}
}
class ViewModel {
final bool isLoading;
final String error;
final List<String> data;
ViewModel({this.isLoading, this.error, this.data});
static ViewModel create(Store<AppState> store) {
return ViewModel(
isLoading: store.state.isLoading,
error: store.state.error,
data: store.state.data,
);
}
}