Flutter状态管理插件redux_compact的使用

Flutter状态管理插件redux_compact的使用

Redux Compact

Redux Compact 是一个旨在减少维护 Flutter Redux 应用程序时大量样板代码的库。该库提供了一组中间件和一个 reducer,用于拦截一种特殊的动作称为 Compact Action。这种动作可以直接访问状态,并且可以是同步或异步的,同时提供了链式调用动作的能力。动作的 reducer 是一个名为 reduce 的方法,允许你在动作本身中进行相应状态的更改。

这种方法消除了维护单独的动作和 reducer 文件夹以及创建和分发多个动作来处理异步状态的需要。

使用方法

前提条件

本文档假设你已经熟悉 Redux 和 Flutter Redux,并了解它们的核心概念、设置和使用方法。

示例代码

初始化 Store

首先,按照 Flutter Redux 的推荐方式创建你的 Store,并添加 Redux Compact 中间件和 reducer。

import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:redux/redux.dart';
import 'package:redux_compact/redux_compact.dart';

void main() {
  final compactReducer = ReduxCompact.createReducer<int>();
  final compactMiddleware = ReduxCompact.createMiddleware<int>();

  final store = Store<int>(
    compactReducer, // 添加 compactReducer
    initialState: 0,
    middleware: [
      compactMiddleware, // 添加 compactMiddleware
    ],
  );

  runApp(MyApp(
    store: store,
    title: "Redux Compact",
  ));
}

class MyApp extends StatelessWidget {
  final Store<int> store;
  final String title;

  const MyApp({Key? key, required this.store, required this.title})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return StoreProvider<int>(
      store: store,
      child: MaterialApp(
        title: title,
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: CounterWidget(),
      ),
    );
  }
}

定义 Compact Action

然后,定义一个扩展 CompactAction 的动作并分发它。

class IncrementCountAction extends CompactAction<int> {
  final int incrementBy;

  IncrementCountAction(this.incrementBy);

  @override
  int reduce() {
    return state + incrementBy;
  }
}

创建 ViewModel

BaseModel 是一个方便的类,可以快速为 Redux StoreConnector 创建 ViewModel。它直接访问 store 状态和 dispatch 函数。你可以在模型或小部件中 dispatch 动作。

class _VM extends BaseModel<int> {
  final int? count;

  _VM(Store<int> store, {this.count = 0}) : super(store);

  void incrementCount() {
    dispatch(IncrementCountAction(1));
  }

  @override
  _VM fromStore() {
    final count = state;
    return _VM(store, count: count);
  }
}

使用 StoreConnector

最后,在小部件中使用 StoreConnector 来初始化 ViewModel 并构建 UI。

class CounterWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StoreConnector<int, _VM>(
      converter: (store) => _VM(store).fromStore(), // 初始化 BaseModel
      builder: (context, vm) => render(context, vm),
    );
  }

  Widget render(BuildContext context, _VM vm) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Redux Compact"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('You have pushed the button this many times:'),
            Text(
              vm.count.toString(),
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: vm.incrementCount, // 通过 BaseModel dispatch
        tooltip: "Increment",
        child: Icon(Icons.add),
      ),
    );
  }
}

全局错误处理

你可以通过在创建中间件时实现 onError 函数来添加全局错误处理。该函数接受 dynamic error 和 dispatch 函数作为参数。

final compactMiddleware = ReduxCompact.createMiddleware<int>(
  onError: (error, dispatch) => yourErrorFunction(error, dispatch),
);

Compact Action

为了使用 Redux Compact,你必须分发一个扩展 CompactAction 的动作。所有紧凑动作都必须实现 reduce 方法,这是动作的 reducer。reduce 方法可以直接访问实例变量、dispatch 函数和 store 状态。

同步动作

class IncrementCountAction extends CompactAction<int> {
  final int incrementBy;

  IncrementCountAction(this.incrementBy);

  @override
  int reduce() {
    return state + incrementBy;
  }
}

异步动作

要创建异步动作,只需实现 makeRequest() 方法作为一个 Future。随着请求的执行,request 实例变量的值会改变,从而允许你根据情况进行状态更改。

class FetchDataAction extends CompactAction<AppState> {
  @override
  Future<void> makeRequest() async {
    final url = "http://example.com/data";
    final response = await http.get(Uri.parse(url));

    if (response.statusCode == 200) {
      return response.body;
    } else {
      throw Exception('Failed to load data');
    }
  }

  @override
  AppState reduce() {
    if (request.loading) {
      return state.copy(isLoading: request.loading);
    }

    if (request.hasError) {
      return state.copy(errorMsg: request.error.toString());
    }

    return state.copy(data: request.data);
  }
}

链式调用动作

Compact Action 提供了两个辅助函数:before 和 after。这两个方法都可以直接访问 state、dispatch 函数和类实例变量。因此,你可以在当前动作运行之前或之后调用或 dispatch 其他函数或动作。

class IncrementCountAction extends CompactAction<int> {
  final int incrementBy;

  IncrementCountAction(this.incrementBy);

  @override
  int reduce() {
    return state + incrementBy;
  }

  @override
  void before() {
    dispatch(SetPreviousCountAction(state));
  }

  @override
  void after() {
    dispatch(FetchDataAction());
  }
}

总结

Redux Compact 通过简化动作和 reducer 的定义,减少了大量样板代码,使得状态管理更加简洁高效。希望本文档能帮助你更好地理解和使用 Redux Compact。如果你有任何问题或建议,欢迎在评论区留言。


更多关于Flutter状态管理插件redux_compact的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter状态管理插件redux_compact的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中,redux_compact 是一个用于状态管理的插件,它是对 Redux 模式的简化封装,使得状态管理更加简洁和高效。下面是一个使用 redux_compact 进行状态管理的代码示例,包括创建 Redux store、定义 actions 和 reducers,以及在 Flutter widget 中使用这些状态。

1. 添加依赖

首先,在 pubspec.yaml 文件中添加 redux_compact 的依赖:

dependencies:
  flutter:
    sdk: flutter
  redux_compact: ^x.y.z  # 替换为最新版本号

2. 定义状态 (State)

假设我们有一个简单的计数器应用,状态是一个整数:

import 'package:redux_compact/redux_compact.dart';

class CounterState implements StateType {
  final int count;

  CounterState(this.count);

  // 实现 Equatable 的 props 方法,用于比较两个状态是否相等
  @override
  List<Object?> get props => [count];
}

3. 定义动作 (Actions)

接下来,定义增加和减少计数的动作:

import 'package:redux_compact/redux_compact.dart';

enum CounterActionTypes {
  INCREMENT,
  DECREMENT,
}

class CounterActions {
  static Action increment() => Action(CounterActionTypes.INCREMENT);
  static Action decrement() => Action(CounterActionTypes.DECREMENT);
}

4. 定义 Reducer

然后,定义处理这些动作的 reducer:

import 'package:redux_compact/redux_compact.dart';
import 'counter_state.dart';
import 'counter_actions.dart';

CounterState counterReducer(CounterState state, Action action) {
  CounterState newState;
  switch (action.type) {
    case CounterActionTypes.INCREMENT:
      newState = CounterState(state.count + 1);
      break;
    case CounterActionTypes.DECREMENT:
      newState = CounterState(state.count - 1);
      break;
    default:
      newState = state;
  }
  return newState;
}

5. 创建 Store

使用 ReduxCompact 创建 store,并传入初始状态和 reducer:

import 'package:redux_compact/redux_compact.dart';
import 'counter_state.dart';
import 'counter_reducer.dart';

final store = ReduxCompact<CounterState>(
  initialState: CounterState(0),
  reducer: counterReducer,
);

6. 在 Flutter Widget 中使用 Store

最后,在 Flutter widget 中使用 Provider 包装应用,并使用 connect 函数将状态和动作绑定到 widget:

import 'package:flutter/material.dart';
import 'package:redux_compact/redux_compact.dart';
import 'store.dart';
import 'counter_actions.dart';

void main() {
  runApp(Provider<CounterState>(
    store: store,
    child: MyApp(),
  ));
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: CounterScreen(),
    );
  }
}

class CounterScreen extends StatelessWidget {
  CounterScreen() {
    // 使用 connect 函数将状态和动作绑定到 widget
    connect<CounterState>(
      mapStateToProps: (state) => ({
        count: state.count,
      }),
      mapDispatchToProps: (dispatch) => ({
        increment: () => dispatch(CounterActions.increment()),
        decrement: () => dispatch(CounterActions.decrement()),
      }),
      component: this,
    );
  }

  @override
  Widget build(BuildContext context) {
    final stateProps = getStateProps(context)!;
    final dispatchProps = getDispatchProps(context)!;

    return Scaffold(
      appBar: AppBar(
        title: Text('Counter'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '${stateProps.count}',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: dispatchProps.increment,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
    );
  }
}

在这个示例中,我们创建了一个简单的计数器应用,使用 redux_compact 管理应用的状态。connect 函数用于将 Redux store 的状态和操作映射到 Flutter widget 中,从而允许我们在 widget 中访问和修改状态。

回到顶部