Flutter扩展功能插件bloc_ext的使用

Flutter扩展功能插件bloc_ext的使用

bloc_ext 是一个用于 bloc 中的 Cubit 的扩展包。CubitEx 引入了一些很酷的功能,现在每个 Cubit 都会有以下功能:

  • 发送动作
  • 过滤动作
  • 添加效果
  • 不同 Cubit 之间的通信(尽管 Cubit 是独立的)
  • RxDart 的完整功能

请参阅 示例。此示例包含 countertodo 页面,这些页面展示了 CubitEx 的开箱即用功能。

CounterCubit 示例

import 'package:bloc/bloc.dart';
import 'package:bloc_ext/bloc_ext.dart';
import 'package:rxdart/rxdart.dart';

import '../widgets/StreamConsumer.dart';

// 定义状态类
class CounterState extends Cubit<int> with CubitEx {
  CounterState() : super(0);

  // 增加计数
  void inc() => emit(state + 1);

  // 减少计数
  void dec() => emit(state - 1);

  // 异步增加计数
  void asyncInc() async {
    dispatch(Action(type: 'asyncInc'));
    await Future.delayed(const Duration(seconds: 1));
    inc();
  }

  // 定义异步增加的效果函数
  EffectFun<int> get asyncIncBy => effect<int>((num$) =>
      num$
          .doOnData((_) => dispatch(Action(type: 'asyncInc')))
          .delay(const Duration(seconds: 1))
          .doOnData((by) => emit(state + by)));

  // 获取计数流
  Stream<SCResponse> get count$ => Rx.merge([
        action$.whereType('asyncInc').mapTo(SCLoading()),
        stream$.map((data) => data > 10
            ? SCError('Counter is out of the range.')
            : SCData('$data')),
      ]);
}

TodoCubit 示例

import 'package:bloc/bloc.dart';
import 'package:bloc_ext/bloc_ext.dart';
import 'package:rxdart/rxdart.dart';

import '../api/todoApi.dart';
import './searchCategory.dart';

// 定义状态类
class TodoCubit extends Cubit<List<Todo>> with CubitEx {
  TodoCubit() : super([]) {
    $initEx();
  }

  @override
  void onInit() {
    loadTodos();
  }

  // 加载待办事项
  void loadTodos() {
    getTodos().listen(emit);
  }

  // 添加待办事项
  void add(String description) {
    addTodo(Todo(description: description))
        .listen((todo) => emit([...state, todo]));
  }

  // 更新待办事项
  void update(Todo todo) {
    updateTodo(todo).listen(
        (todo) => emit([
              for (var item in state)
                if (item.id == todo.id) todo else item,
            ]),
       onError: (error) {
      dispatch(TodoErrorAction(error));
    });
  }

  // 删除待办事项
  void remove(Todo todo) {
    removeTodo(todo).listen(
        (todo) => emit(state.where((item) => item.id != todo.id).toList()));
  }

  // 获取活跃待办事项信息流
  Stream<String> get activeTodosInfo$ => stream$
      .map((todos) => todos.where((todo) => !todo.completed).toList())
      .map((todos) => '${todos.length} items left');

  // 结合多个Cubit (TodoCubit, SearchCategoryCubit) 并返回单个待办事项流
  Stream<List<Todo>> get todo$ => 
      Rx.combineLatest3<List<Todo>, SearchCategory, String, List<Todo>>(
          stream$,
          remoteStream<SearchCategoryCubit, SearchCategory>(),
          action$
              .isA<SearchInputAction>()
              .debounceTime(const Duration(milliseconds: 320))
              .map((action) => action.searchText)
              .startWith(''),
          (todos, category, searchText) {
              if (searchText.isNotEmpty) {
                  todos = todos.where((todo) => todo.description
                            .toLowerCase()
                            .contains(searchText.toLowerCase()))
                            .toList();
              }
              switch (category) {
                case SearchCategory.Active:
                  return todos.where((todo) => !todo.completed).toList();
                case SearchCategory.Completed:
                  return todos.where((todo) => todo.completed).toList();
                default:
                  return todos;
              }
      });
}

// 定义错误动作类
class TodoErrorAction extends Action {
  final dynamic error;
  TodoErrorAction(this.error);
}

// 定义搜索输入动作类
class SearchInputAction extends Action {
  final String searchText;
  SearchInputAction(this.searchText);
}

SearchCategoryCubit 示例

import 'package:bloc/bloc.dart';
import 'package:bloc_ext/bloc_ext.dart';

// 定义搜索类别枚举
enum SearchCategory { All, Active, Completed }

// 定义搜索类别Cubit
class SearchCategoryCubit extends Cubit<SearchCategory> with CubitEx {
  SearchCategoryCubit() : super(SearchCategory.All) {
    $initEx();
  }

  // 设置搜索类别
  void setCategory(SearchCategory category) => emit(category);
}

主应用示例

import 'package:example/states/counter.dart';
import 'package:flutter/material.dart';
import 'package:get/instance_manager.dart';
import 'package:get/route_manager.dart';

import './states/todo.dart';
import './pages/counterPage.dart';
import './pages/todoPage.dart';
import './states/searchCategory.dart';

void main() {
  runApp(GetMaterialApp(
    smartManagement: SmartManagement.keepFactory,
    debugShowCheckedModeBanner: false,
    getPages: [
      GetPage(
          name: '',
          page: () => CounterPage(),
          binding: BindingsBuilder(() {
            Get.lazyPut(() => CounterState());
          })),
      GetPage(
          name: '/todo',
          page: () => TodoPage(),
          transition: Transition.zoom,
          binding: BindingsBuilder(() {
            Get.put<TodoState>(TodoState(), permanent: true);
            Get.put<SearchCategoryState>(SearchCategoryState(), permanent: true);
          }))
    ],
    initialRoute: '',
  ));
}

更多关于Flutter扩展功能插件bloc_ext的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter扩展功能插件bloc_ext的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


bloc_ext 是一个用于 Flutter 的扩展功能插件,旨在简化 flutter_bloc 的使用,并提供一些额外的功能来增强开发体验。bloc_ext 可以帮助你更容易地管理 BLoC(Business Logic Component)状态,减少样板代码,并提高代码的可读性和可维护性。

以下是一些常见的 bloc_ext 功能和使用方法:

1. 安装 bloc_ext

首先,你需要在 pubspec.yaml 文件中添加 bloc_ext 依赖:

dependencies:
  flutter:
    sdk: flutter
  bloc_ext: ^0.1.0 # 请检查最新版本

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

2. 基本用法

bloc_ext 提供了一些扩展方法和工具来简化 flutter_bloc 的使用。以下是一些常见的用法示例:

2.1 简化 BlocProvider 的创建

bloc_ext 提供了一个 BlocProvider.ext 方法来简化 BlocProvider 的创建:

import 'package:flutter/material.dart';
import 'package:bloc_ext/bloc_ext.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

class MyBloc extends Cubit<int> {
  MyBloc() : super(0);

  void increment() => emit(state + 1);
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return BlocProvider.ext(
      create: (context) => MyBloc(),
      child: MaterialApp(
        home: MyHomePage(),
      ),
    );
  }
}

2.2 简化 BlocBuilder 的使用

bloc_ext 提供了一个 BlocBuilder.ext 方法来简化 BlocBuilder 的使用:

class MyHomePage extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Bloc Ext Example'),
      ),
      body: Center(
        child: BlocBuilder.ext<MyBloc, int>(
          builder: (context, state) {
            return Text('Count: $state');
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => context.read<MyBloc>().increment(),
        child: Icon(Icons.add),
      ),
    );
  }
}

2.3 简化 BlocListener 的使用

bloc_ext 提供了一个 BlocListener.ext 方法来简化 BlocListener 的使用:

class MyHomePage extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Bloc Ext Example'),
      ),
      body: Center(
        child: BlocListener.ext<MyBloc, int>(
          listener: (context, state) {
            if (state == 5) {
              ScaffoldMessenger.of(context).showSnackBar(
                SnackBar(content: Text('Count reached 5!')),
              );
            }
          },
          child: BlocBuilder.ext<MyBloc, int>(
            builder: (context, state) {
              return Text('Count: $state');
            },
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => context.read<MyBloc>().increment(),
        child: Icon(Icons.add),
      ),
    );
  }
}
回到顶部