Flutter业务逻辑管理插件ff_bloc的使用

Flutter业务逻辑管理插件ff_bloc的使用

导入

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

dependencies:
  ff_bloc: 1.0.3

为什么使用ff_bloc?

使用 ff_bloc 的好处包括:

  • 事件处理applyAsync 方法使得事件处理更加简单且快速。
  • 文件结构:类似于功能模块的文件结构更适合代码生成和快速导航。
  • 状态管理:易于理解和使用的基本状态管理。
  • 订阅和取消订阅:基本抽象用于订阅和取消订阅。
  • 自动清理资源:通过 GetIt 管理生命周期。

示例代码

以下是一个完整的示例代码,展示了如何使用 ff_bloc 来管理业务逻辑。

主应用文件

main.dart 中设置应用根组件,并初始化 ff_bloc

import 'package:example/you_awesome/index.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: YouAwesomePage(
        bloc: YouAwesomeBloc(
          provider: YouAwesomeProvider(),
        ),
      ),
    );
  }
}

Bloc 类

定义一个 YouAwesomeBloc 类来处理业务逻辑。

import 'package:equatable/equatable.dart';
import 'package:ff_bloc/ff_bloc.dart';
import 'package:get_it/get_it.dart';

class YouAwesomeBloc extends FFBloc<YouAwesomeEvent, YouAwesomeState> {
  YouAwesomeBloc({
    required this.provider,
    super.initialState = const YouAwesomeState(),
  });

  final YouAwesomeProvider provider;

  [@override](/user/override)
  Iterable<StreamSubscription>? initSubscriptions() {
    return [];
  }

  [@override](/user/override)
  YouAwesomeState onErrorState(Object error) => 
      state.copyWith(error: error, isLoading: false);
}

状态类

定义一个 YouAwesomeState 类来表示状态。

class YouAwesomeState extends FFState<YouAwesomeState, YouAwesomeViewModel> {
  const YouAwesomeState({
    super.version = 0,
    super.isLoading = false,
    super.data,
    super.error,
  });

  [@override](/user/override)
  StateCopyFactory<YouAwesomeState, YouAwesomeViewModel> getCopyFactory() => YouAwesomeState.new;
}

视图模型类

定义一个 YouAwesomeViewModel 类来表示数据模型。

class YouAwesomeViewModel extends Equatable {
  const YouAwesomeViewModel({
    required this.items,
  });

  final List<YouAwesomeModel>? items;

  [@override](/user/override)
  List<Object?> get props => [items];

  YouAwesomeViewModel copyWith({
    List<YouAwesomeModel>? items,
  }) {
    return YouAwesomeViewModel(
      items: items ?? this.items,
    );
  }
}

事件类

定义一个 LoadYouAwesomeEvent 类来处理加载事件。

class LoadYouAwesomeEvent extends YouAwesomeEvent {
  LoadYouAwesomeEvent({required this.id});
  final String? id;

  static const String _name = 'LoadYouAwesomeEvent';

  [@override](/user/override)
  String toString() => _name;

  [@override](/user/override)
  Stream<YouAwesomeState> applyAsync({required YouAwesomeBloc bloc}) async* {
    yield bloc.state.copyWithWithoutError(isLoading: true);
    final result = await bloc.provider.fetchAsync(id);
    yield bloc.state.copyWithWithoutError(
      isLoading: false,
      data: YouAwesomeViewModel(items: result),
    );
  }
}

UI 组件

使用 BlocBuilder 构建 UI 组件以响应状态变化。

[@override](/user/override)
Widget build(BuildContext context) {
  return BlocBuilder<YouAwesomeBloc, YouAwesomeState>(
    bloc: widget.bloc,
    builder: (
      BuildContext context,
      YouAwesomeState currentState,
    ) {
      return currentState.when(
        onLoading: () => const CircularProgressIndicator(),
        onEmpty: (data) => _Empty(),
        onData: (data) => _BodyList(data: data),
        onError: (e) => Center(
          child: Column(
            children: [
              Text(e.toString()),
              TextButton(
                onPressed: _load,
                child: const Text('ReLoad'),
              )
            ],
          ),
        ),
      );
    },
  );
}

高级用法

以下是一个自定义 CustomBloc 的示例,展示了如何覆盖日志记录逻辑。

abstract class CustomBloc<Event extends CustomBlocEvent<State, Bloc<Event, State>>, State extends CustomState<Self, DataT>> extends FFBloc<Event, State> {
  CustomBloc({
    required super.initialState,
    required this.logger,
  });

  [@nonVirtual](/user/nonVirtual)
  final Logger logger;

  [@override](/user/override)
  void onObserver({required Event event}) {
    logger.i('on event: ${event.toString()}', tag: runtimeType.toString());
  }

  [@override](/user/override)
  void onErrorObserver({required Event event, required Object error, required StackTrace stackTrace}) {
    logger.e(
      error.toString(),
      exception: error,
      tag: event.runtimeType.toString(),
      stackTrace: stackTrace,
    );
  }

  [@override](/user/override)
  void onTransitionObserver({required Transition<Event, State> transition}) {
    logger.i('onTransition: ${transition.toString()}', tag: runtimeType.toString());
  }
}

[@immutable](/user/immutable)
abstract class CustomState<Self, DataT> extends FFState<Self, DataT> {
  const CustomState({
    required super.version,
    required super.isLoading,
    required super.data,
    required super.error,
  });
}

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

1 回复

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


当然,下面是一个关于如何在Flutter项目中使用ff_bloc插件进行业务逻辑管理的示例代码案例。ff_bloc(通常我们提到的是flutter_bloc,但这里假设ff_bloc是一个类似的概念或自定义的BLoC库,用于管理业务逻辑)主要用于将业务逻辑从UI层分离出来,提高代码的可维护性和可测试性。

1. 添加依赖

首先,确保在你的pubspec.yaml文件中添加了ff_bloc(或flutter_bloc)的依赖:

dependencies:
  flutter:
    sdk: flutter
  ff_bloc: ^x.y.z  # 替换为实际版本号

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

2. 创建BLoC和事件/状态

假设我们有一个简单的计数器应用,我们需要一个BLoC来处理增加和减少计数的事件,并管理计数器的状态。

创建事件类

// 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(this.count);

  @override
  List<Object> get props => [count];
}

创建BLoC类

// counter_bloc.dart
import 'package:bloc/bloc.dart';
import 'package:ff_bloc/ff_bloc.dart';  // 假设ff_bloc是BLoC库
import 'counter_event.dart';
import 'counter_state.dart';

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

  // Helper method to create a new state with updated count
  CounterState copyWith(int count) {
    return CounterState(count);
  }
}

3. 在UI中使用BLoC

// main.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';  // 使用flutter_bloc进行UI绑定
import 'counter_bloc.dart';
import 'counter_event.dart';
import 'counter_state.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: BlocProvider(
        create: (context) => CounterBloc(),
        child: CounterScreen(),
      ),
    );
  }
}

class CounterScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Counter App')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            BlocBuilder<CounterBloc, CounterState>(
              builder: (context, state) {
                return Text(
                  'You have pushed the button this many times:',
                  style: Theme.of(context).textTheme.headline4,
                );
              },
            ),
            SizedBox(height: 20),
            BlocBuilder<CounterBloc, CounterState>(
              builder: (context, state) {
                return Text(
                  '${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'),
            ),
          ],
        ),
      ),
    );
  }
}

4. 运行应用

现在你可以运行你的Flutter应用,应该会看到一个简单的计数器界面,可以通过按钮来增加或减少计数。

总结

上述代码展示了如何在Flutter中使用ff_bloc(或类似BLoC库)来管理业务逻辑,将事件和状态分离,提高代码的可维护性和可测试性。希望这个示例对你有帮助!如果你实际使用的是flutter_bloc,只需将ff_bloc替换为flutter_bloc,其他代码基本保持一致。

回到顶部