Flutter状态管理插件smooth_bloc的使用

发布于 1周前 作者 yuanlaile 来自 Flutter

Flutter状态管理插件smooth_bloc的使用

标题

Flutter状态管理插件smooth_bloc的使用

内容

  • 图片

    • Smooth Bloc Logo
    • Smooth Bloc Overview
  • 简介

    • Smooth Bloc 是一个基于 flutter_bloc 的的状态管理代码库,旨在帮助开发者轻松实现 BLoC 模式。它提供了生产质量与维护友好的状态管理解决方案。
    • 这个包的目标是提供最简单的代码基础来实现屏幕中的逻辑、视图和数据/状态三层,并且在不探索所有 flutter_bloc 特性的情况下轻松使用这些特性。在实际项目中,我们通常不会使用所有的 flutter_bloc 功能。
    • Smooth Bloc 已经稳定地应用于超过20个作者的企业应用,并仍在持续增长。
  • 主要功能

    • 状态管理(当然!)
    • 高度定制化的事件驱动函数:
      • 显示加载页面
      • 显示错误对话框
      • 显示消息对话框
    • 监听状态更改
    • 容易控制重建条件
  • 概述

    • Smooth Bloc 中的一个屏幕/功能包含以下三个 Dart 类:
      • Cubit:这个类持有用户交互于视图上的逻辑,并可以控制何时以及如何重建视图。
      • State:这个类包括显示在视图中的属性,并可以在运行时由 Cubit 类更改。
      • View:这个类持有所有的 widget,每当 State 发生变化时,视图会自动重建。视图通常调用 Cubit 的的功能。
  • 安装

    dependencies:  
      # 添加 copy_with_extension (可选)
      copy_with_extension:  
      # 添加 smooth_bloc
      smooth_bloc:
    
    dev_dependencies:  
      # 添加 copy_with_extension_gen (可选)
      copy_with_extension_gen:
    
  • 使用方法

    • 首次设置 Smooth Bloc 允许自定义 Dialog 和 Loading 屏幕,如果需要的话。

      void main() {
        // 设置 SmoothBloc
        SmoothBloc().setUp(
          appLoadingBuilder: (message) {
            // 返回你的自定义 Widget
          },
          appDialogBuilder: (message) {
            // 返回你的自定义 Widget
          },
        );
      
        // 运行应用程序
        runApp(const TestApp());
      }
      
    • 创建状态类 需要继承 BaseState 并实现 stateComparisonProps 的 getter,该 getter 定义了用于比较和识别何时应该重建视图的属性(当状态发生变化时)。 可以使用 copy_with_extension 来生成 .copyWith() 函数,这在 Cubit 的逻辑函数中非常有用。

      //@CopyWith() 是一个可选注解
      @CopyWith()
      class LoginState extends BaseState {
        final bool isLoggedIn;
      
        // 构造函数需要声明默认构造函数的所有属性
        LoginState({
           this.isLoggedIn = false,
        });
      
        @override
        List<Object?> get stateComparisonProps => [
              isLoggedIn,
            ];
      }
      
    • 创建 Cubit 类 继承 BaseCubit 的类将继承上述功能和属性。

      import 'login_state.dart';
      
      class LoginCubit extends BaseCubit<LoginState> {
        LoginCubit() : super(LoginState());
      
        void login(String email, password) {
          try {
            // 调用显示加载屏幕
            showLoading();
            // 假设你已经完成用户身份验证
            // 调用 emit 函数来改变状态并触发屏幕重建
            emit(
              state.copyWith(
                isLoggedIn: true,
              ),
            );
            // 向用户提供消息
            showMessage("You've been logged in!");
          } catch (e) {
            // 在屏幕上显示错误对话框
            handleError(e.toString());
          } finally {
            // 调用隐藏加载屏幕
            hideLoading();
          }
        }
      
        @override
        Future<void> close() {
          // 在关闭 cubit 时执行的操作
          return super.close();
        }
      }
      
    • 创建 View 类 继承 BaseView 的类将继承上述功能。

      import 'login_cubit.dart';
      import 'login_state.dart';
      
      class LoginView extends StatefulWidget {
        const LoginView({super.key});
      
        @override
        State<LoginView> createState() => _LoginViewState();
      }
      
      class _LoginViewState extends BaseView<LoginState, LoginCubit, LoginView> {
        @override
        LoginCubit assignCubit() {
          // 示例返回使用依赖注入
          return GetIt.instance<LoginCubit>();
          // 或返回为常量值
          return LoginCubit();
        }
      
        // 如果 TRUE,则当视图被销毁时,Cubit 关闭函数将不会被调用
        // 默认为 FALSE
        @override
        bool get shouldNotDisposeCubitAndState => false;
      
        // 这是从 AutomaticKeepAliveClientMixin
        @override
        bool get wantKeepAlive => true;
      
        @override
        onNewEvent(BaseEvent event) {
          if (event is PushPageEvent) {
            // 忽略:未使用的局部变量
            final routeName = event.routeName;
            // 推送新视图
          }
          return super.onNewEvent(event);
        }
      
        @override
        bool shouldRebuild(LoginState previous, LoginState current) {
          // 宣布任何允许或不允许视图重建的条件
          return super.shouldRebuild(previous, current);
        }
      
        @override
        onStateChanged(LoginState previous, LoginState current) {
          if (previous.isLoggedIn != current.isLoggedIn && current.isLoggedIn) {
            // 示例:推送至主屏幕
          }
          return super.onStateChanged(previous, current);
        }
      
        @override
        String getErrorMessage(error) {
          // 您可以在这里自定义来自 Cubit 的的错误事件
          // 最常见的用途是本地化
          return super.getErrorMessage(error);
        }
      
        @override
        String getMessage(msg) {
          // 您可以在这里自定义来自 Cubit 的的消息事件
          // 最常见的用途是本地化
          return super.getMessage(msg);
        }
      
        @override
        Widget buildByState(BuildContext context, LoginState state) {
          return MaterialApp(
            title: 'Flutter Demo',
            theme: ThemeData(
              // 这是您的应用程序的主题。
              // 尝试这样做:尝试运行您的应用程序“flutter run”。您会看到应用程序有一个蓝色的工具栏。然后,在不退出应用程序的情况下,尝试将 seedColor 更改为 Colors.green
              // 并再次点击“热重载”(保存您的更改或在支持的 IDE 中点击“热重载”按钮,或者按“r”如果您使用的是命令行启动应用程序)。请注意,计数器没有重置回零;应用程序状态没有丢失。要重置状态,请使用热重启。
              // 大多数代码更改都可以通过热重新加载测试。
              colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
              useMaterial3: true,
            ),
            home: SafeArea(
              child: Scaffold(
                body: Column(
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Text(
                      state.isLoggedIn ? "You're logged in" : "Please sign in!",
                    ),
                    ElevatedButton(
                      onPressed: () {
                        cubit.login("email", "password");
                      },
                      child: const Text("Login"),
                    ),
                    ElevatedButton(
                      onPressed: () {
                        cubit.signOut();
                      },
                      child: const Text("Sign Out"),
                    ),
                  ],
                ),
              ),
            ),
          );
        }
      }
      
    • 示例代码


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

1 回复

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


当然,以下是一个关于如何在Flutter应用中使用smooth_bloc进行状态管理的代码示例。smooth_bloc是一个基于bloc库的轻量级状态管理解决方案,旨在简化状态管理的实现。

首先,确保你的pubspec.yaml文件中包含以下依赖:

dependencies:
  flutter:
    sdk: flutter
  smooth_bloc: ^0.x.x  # 请使用最新版本号
  flutter_bloc: ^8.0.0  # smooth_bloc依赖于flutter_bloc

然后运行flutter pub get来安装这些依赖。

接下来,我们将创建一个简单的计数器应用来展示如何使用smooth_bloc

1. 创建计数器事件类

// 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 {}

2. 创建计数器状态类

// 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];

  CounterState copyWith({int? count}) {
    return CounterState(count: count ?? this.count);
  }
}

3. 创建计数器Bloc类

// counter_bloc.dart
import 'package:bloc/bloc.dart';
import 'package:smooth_bloc/smooth_bloc.dart';
import 'counter_event.dart';
import 'counter_state.dart';

class CounterBloc extends SmoothBloc<CounterEvent, CounterState> {
  CounterBloc() : super(CounterState(count: 0)) {
    on<IncrementEvent>((event, emit) {
      emit(state.copyWith(count: state.count + 1));
    });

    on<DecrementEvent>((event, emit) {
      emit(state.copyWith(count: state.count - 1));
    });
  }
}

4. 创建Flutter UI组件

// main.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:smooth_bloc/smooth_bloc.dart';
import 'counter_bloc.dart';
import 'counter_event.dart';

void main() {
  runApp(
    BlocProvider(
      create: (_) => CounterBloc(),
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Counter App'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '${context.select((CounterState state) => state.count)}',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: Row(
        mainAxisAlignment: MainAxisAlignment.end,
        children: <Widget>[
          FloatingActionButton(
            onPressed: () => context.read<CounterBloc>().add(IncrementEvent()),
            tooltip: 'Increment',
            child: Icon(Icons.add),
          ),
          SizedBox(width: 10),
          FloatingActionButton(
            onPressed: () => context.read<CounterBloc>().add(DecrementEvent()),
            tooltip: 'Decrement',
            child: Icon(Icons.remove),
          ),
        ],
      ),
    );
  }
}

在这个示例中,我们定义了一个简单的计数器应用,其中包含增加和减少计数的事件和状态。通过smooth_bloc,我们可以轻松管理这些状态和事件,并将它们与UI组件绑定。

请注意,smooth_bloc是基于bloc库的一个封装,提供了更简洁的API,特别是在处理状态和事件时。确保你已经熟悉bloc库的基本概念,以便更好地理解和使用smooth_bloc

回到顶部