Flutter状态管理架构插件blocstar的使用

发布于 1周前 作者 gougou168 最后一次编辑是 5天前 来自 Flutter

##Flutter状态管理架构插件blocstar的使用

Blocstar 是一个基于 BLoC 的微型框架,它帮助你结构化 Flutter 代码的布局和编写方式。

为什么使用Blocstar?

有几个原因:

  1. 状态管理 - 虽然 Flutter 本身支持状态管理,但它鼓励将业务逻辑与用户界面混在一起。这不利于测试。庆幸的是,Flutter 也提供了对 Stream 的良好支持,从而产生了 BLoC 模式。

  2. 强制结构 - 虽然 BLoC 可以将业务逻辑移出小部件,但它不对代码应该如何布局提出任何意见。虽然自由有其优点,但一个主要缺点是这会导致代码风格的多样性,这在后期阅读不一致编写的 BLoC 时会增加认知负担。显然,当代码由团队而非个人编写时,问题变得更加严重,导致代码库中的变化更大。

Blocstar的目标

  1. 稳健、轻量且易于学习的库 - 拿起来,试用一下,看看它是否适合你,所有这些都可以在半小时内完成。

  2. 最小化样板代码 - 关注你的代码,而不是关注那些繁琐的样板代码,让代码保持简洁,以便几周、几个月或几年后你还能轻松理解代码。

开始使用

好的,让我们看看它如何工作。

安装

安装页面 安装 blocstar。

Blocstar 的哲学(或一些背景信息)

Blocstar 的一个关键原则是 Flutter 应用程序通常由以下部分组成:

  1. 用户界面 - 这个部分自解释。

  2. 业务逻辑 - 执行应用核心功能的规则。

  3. 上下文(或状态) - 这些是业务逻辑在执行时需要考虑的情况(例如,用户是否已登录?应用是否正在执行异步操作?上次操作是否发生错误等)。

  4. 事件(例如按钮点击、接收推送通知、操作失败等)。

另一个原则是你的应用程序应该是模块化的,每个模块应该维护一个全局可用的单一数据源。这个数据源构成了我们的上下文。接下来,我们将使用“模块”这个词来指代执行特定功能的一组小部件和其他文件。例如,“用户注册”是一个模块,而“登录”则是另一个模块。

现在,我们已经介绍了基础知识,让我们看看 Blocstar 如何看待这些元素,并如何协调它们之间的交互。

使用示例

1. Blocstar 上下文

如上所述,Blocstar 应用程序是模块化的,我们为每个模块使用一个专用的数据源。此数据源应包含可以被模块内多个类访问的所有变量和常量。

上下文就是一个简单的 Flutter 类,继承自 Blocstar 提供的 BlocstarContextBase 基类。

BlocstarContextBase 基类提供以下行为:

  1. 跟踪模块是否正在进行异步操作,并允许你在繁忙和空闲状态下进行行为定制(例如自动显示进度指示器,当空闲时显示主用户界面)。

  2. 捕获超时的异步操作,并像上面跟踪繁忙状态一样,你可以指定在操作超时时和按时完成时显示什么内容。

  3. 捕获来自异步操作的错误,并且你还可以决定在发生错误时显示什么内容(你还会得到错误信息,这样不是很好吗?)。

  4. 一种类似于 JavaScript 的扩展方法,使你能够快速可靠地更改上下文,而无需每次更改一个 final 变量时传递数百万个参数给类构造函数。

示例 Blocstar 上下文
class CounterContext extends BlocstarContextBase<CounterContext> {
  final int count;
  final String description;

  CounterContext(BlocstarContextBase<BlocstarContextBase<CounterContext>> logic, {this.count, this.description}) : super(logic);

  [@override](/user/override)
  merge({int newCount, String newDescription}) {
    return new CounterContext(logic,
        count: resolveValue(count, newCount),
        description: resolveValue(description, newDescription));
  }
}

要点:

  1. 它只是一个继承自 Blocstar 的 BlocstarContextBase 的简单类。

  2. 你可以创建自己的自定义变量。

  3. 自定义变量应为 final 并作为命名参数传递给构造函数。

  4. 构造函数中的 BlocstarContextBase<BlocstarContextBase<CounterContext>> logic 参数 - 这是处理我们业务逻辑的对象实例。将它传递给上下文允许 Blocstar 自动处理广播上下文更改到模块的其余部分。

  5. merge 方法。这是类似于 JavaScript 的扩展方法。你可以选择性地传递所有或仅部分参数。在该方法中,只需创建一个新的上下文类实例,确保在传递参数值时运行它们通过 Blocstar 的 resolveValue 方法,该方法确定是使用现有变量值还是用新提供的值覆盖它。由于我们在上下文构造函数中传递了 logic 对象,只需创建新的类实例就会触发上下文更改的广播,模块的其余部分现在知道评估更新后的上下文并相应地做出反应。

2. 业务逻辑

下一步是引入业务逻辑。业务逻辑应该是唯一读写上下文的地方。每当上下文更新时,模块的业务逻辑类应该广播发生了更改,整个模块都可以查看新的上下文并做出反应。

示例 Blocstar 业务逻辑类
class CounterBloc extends BlocstarLogicBase<CounterContext> {
  [@override](/user/override)
  Future initializeAsync() async {
    context = new CounterContext(this,
        count: 0, description: "Button Press Count");
  }

  buttonPressedAsync(
    int duration,
  ) async {
    final incrementedCount = await runAsync(
        function: () async => await _incrementAsync(duration),
        timeoutSeconds: 3);

    // 超时调用或调用出错时返回null
    if (incrementedCount != null) {
      context.merge(newCount: incrementedCount);
    }
  }

  /// 此方法模拟异步操作,通过用户指定的秒数延迟来实现增量。
  /// 它允许我们看到 Blocstar 如何处理异步调用。
  Future<int> _incrementAsync(int duration) async {
    final incrementedCount =
        await Future.delayed(new Duration(seconds: duration), () {
      return context.count + 1;
    });
    return incrementedCount;
  }
}

要点:

  1. 你的业务逻辑类需要扩展 BlocstarLogicBase

  2. BlocstarLogicBase 是一个泛型类,期望使用一个 Context 类型的类型参数。在这个例子中,我们将使用前面创建的 Context 类。泛型基类确保类型安全,并带来所有好处,比如更少的错误、更易读的代码,当然还有长期喜爱的 IDE 自动完成功能。

  3. 你需要实现一个 initializeAsync 方法。在此方法中,你必须首先初始化上下文。当然,你还可以做其他准备。

  4. 在实例化上下文时,业务逻辑类向上下文传递自身的一个实例,正如上面提到的,这个实例允许 Blocstar 广播上下文更改到模块的其余部分。

  5. BlocstarContextBase 基类为我们提供了一个名为 context 的对象。这是我们创建的上下文对象的一个实例。我们可以在这里找到我们声明的所有公共变量和/或方法。此外,context 对象还包含 merge 方法。

  6. 异步方法调用被包装在 Blocstar 的 runAsync 方法中。该方法接受两个参数;第一个是要调用的异步方法,第二个是在方法被认为超时之前等待的秒数。如果异步方法调用出现超时或错误,runAsync 方法返回 null。重要的是,在超时或错误发生时,上下文会自动更新并发送广播。在下一节中,我们将看到如何在 UI 中处理这些广播。最后,如果异步方法成功完成,runAsync 方法返回该方法的值。此值可以输入 merge 方法以更新上下文。

  7. merge 方法允许我们通过选择性地传递一个或多个值来更新上下文。如果你按照上述设置上下文,那么调用 merge 方法不仅会更新你的上下文,还会广播更改到模块的其余部分。

3. 用户界面

这是我们将所有内容整合在一起的地方。Blocstar 的一个关键原则是采用模块化的方法来构建功能。因此,Blocstar 将期望我们在步骤 2 中构建的业务逻辑类绑定到恰好一个部件,然后这个主部件的责任是托管其余的 UI。这允许我们为用户界面和业务逻辑及模块上下文提供一个单一的连接点。

class Counter extends StatefulWidget {
  [@override](/user/override)
  State<StatefulWidget> createState() {
    return new _CounterState();
  }
}

class _CounterState extends BlocstarState<Counter, CounterBloc> {
  [@override](/user/override)
  Widget rootWidget() {
    return Scaffold(
        appBar: AppBar(
          title: Text("Blocstar Counter Example"),
        ),
        body: _body);
  }

  Widget get _body {
    if (logic.initialized == false) {
      logic.initializeAsync();
      return Text("Initializing");
    } else {
      if (logic.context.actionState.busy) {
        return Text("Working. Please Wait");
      } elseif (logic.context.actionState.lastActionTimedOut) {
        return Text("Last Action Timed Out");
      } else if (logic.context.actionState.errorOccuredOnLastAction) {
        return Text("Last Action Failed");
      } else {
        return Text("Count Is ${logic.context.count.toString()}");
      }
    }
  }
}

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

1 回复

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


虽然“blocstar”并不是一个广为人知的Flutter插件或库(截至我最后的知识更新),但基于名称推测,它可能是一个与Bloc状态管理架构相关的工具或扩展。由于Flutter社区中Bloc状态管理非常流行,我们可以基于Flutter的Bloc库给出一个基本的示例,展示如何使用Bloc进行状态管理。

以下是一个简单的Flutter应用示例,展示了如何使用flutter_bloc库来实现一个计数器应用:

  1. 添加依赖: 首先,在pubspec.yaml文件中添加flutter_bloc依赖:

    dependencies:
      flutter:
        sdk: flutter
      flutter_bloc: ^8.0.0  # 请检查最新版本号
  2. 创建Bloc事件和状态: 创建两个Dart文件,一个用于定义事件(counter_event.dart),另一个用于定义状态(counter_state.dart)。

    counter_event.dart

    import 'package:equatable/equatable.dart';
    
    abstract class CounterEvent extends Equatable {
      const CounterEvent();
    
      @override
      List<Object?> get props => [];
    }
    
    class IncrementEvent extends CounterEvent {}
    class DecrementEvent extends CounterEvent {}

    counter_state.dart

    import 'package:equatable/equatable.dart';
    
    class CounterState extends Equatable {
      final int count;
    
      const CounterState({required this.count});
    
      @override
      List<Object?> get props => [count];
    }
  3. 创建Bloc: 创建一个Bloc类来处理事件并生成新的状态(counter_bloc.dart)。

    import 'package:bloc/bloc.dart';
    import 'counter_event.dart';
    import 'counter_state.dart';
    
    class CounterBloc extends Bloc<CounterEvent, CounterState> {
      CounterBloc() : super(const CounterState(count: 0));
    
      @override
      Stream<CounterState> mapEventToState(CounterEvent event) async* {
        if (event is IncrementEvent) {
          yield state.copyWith(count: state.count + 1);
        } else if (event is DecrementEvent) {
          yield state.copyWith(count: state.count - 1);
        }
      }
    }
  4. 创建UI: 在main.dart文件中创建Flutter UI,并使用BlocBuilder来监听状态变化。

    import 'package:flutter/material.dart';
    import 'package:flutter_bloc/flutter_bloc.dart';
    import 'counter_bloc.dart';
    import 'counter_event.dart';
    
    void main() {
      runApp(BlocProvider<CounterBloc>(
        create: (_) => CounterBloc(),
        child: MyApp(),
      ));
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(title: Text('Flutter Bloc Counter')),
            body: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text(
                    '${context.bloc<CounterBloc>().state.count}',
                    style: Theme.of(context).textTheme.headline4,
                  ),
                  SizedBox(height: 20),
                  ElevatedButton(
                    onPressed: () => context.read<CounterBloc>().add(IncrementEvent()),
                    child: Text('Increment'),
                  ),
                  SizedBox(height: 10),
                  ElevatedButton(
                    onPressed: () => context.read<CounterBloc>().add(DecrementEvent()),
                    child: Text('Decrement'),
                  ),
                ],
              ),
            ),
          ),
        );
      }
    }

这个示例展示了如何使用flutter_bloc库来创建一个简单的计数器应用。它涵盖了定义事件和状态、创建Bloc类以及使用BlocBuilder在UI中监听状态变化的基本步骤。如果“blocstar”确实是一个与Bloc相关的工具或库,它可能会提供额外的功能或简化这些步骤,但基于当前的信息,上述示例提供了一个良好的Bloc状态管理基础。

回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!