Flutter状态管理插件redux_compact的使用

Flutter状态管理插件redux_compact的使用

Redux Compact

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

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

使用方法

前提条件

本文档假设你已经熟悉 ReduxFlutter 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 errordispatch 函数作为参数。

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 提供了两个辅助函数:beforeafter。这两个方法都可以直接访问 statedispatch 函数和类实例变量。因此,你可以在当前动作运行之前或之后调用或 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 中访问和修改状态。

回到顶部