Flutter事件监听插件bloc_action_listener的使用

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

Flutter事件监听插件bloc_action_listener的使用

为什么使用这个包?

在许多情况下,您可能希望您的UI响应那些不一定与状态变化相关的操作。例如:

  • 显示对话框
  • 显示SnackBar
  • 导航到不同的屏幕或路由

使用“Bloc Action Listener”,您可以更方便地实现这些功能。

开始使用

1. 定义您的动作

您可以根据需要创建动作。这些动作将被分发并在UI中监听。

abstract class ExampleAction {}

class ShowTestDialogAction extends ExampleAction {
  final String title;
  final String content;

  ShowTestDialogAction({
    required this.title,
    required this.content,
  });
}

class ShowSnackbarAction extends ExampleAction {
  final String content;

  ShowSnackbarAction({required this.content});
}
2. 扩展您的Bloc或Cubit

使用 BlocActionsMixin 来扩展您的 Bloc 或 Cubit。这个 mixin 提供了 addAction() 方法,允许您分发定义的动作。

class ExampleCubit extends Cubit<ExampleState> with BlocActionsMixin<ExampleState, ExampleAction> {
  ExampleCubit() : super(ExampleInitial());

  void onShowTestDialogPressed() {
    addAction(
      ShowTestDialogAction(
        title: 'Test dialog',
        content: 'Test dialog message',
      ),
    );
  }

  void onShowTestSnackbarPressed() {
    addAction(ShowSnackbarAction(content: 'Test snackbar message'));
  }
}
3. 在UI中监听和处理动作

使用 BlocActionListener 小部件,您可以在UI中响应分发的动作。

BlocActionListener<ExampleCubit, ExampleAction>(
  listener: (context, action) {
    if (action is ShowTestDialogAction) {
      final title = action.title;
      final content = action.content;
      showDialog(
        context: context,
        builder: (context) => AlertDialog(title: Text(title), content: Text(content)),
      );
    }
    if (action is ShowSnackbarAction) {
      final content = action.content;
      ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(content)));
    }
  },
);

完整示例Demo

以下是一个完整的示例,展示了如何使用 bloc_action_listener 插件来实现显示对话框和SnackBar的功能。

import 'package:bloc_action_listener/bloc_action_listener.dart';
import 'package:bloc_action_listener/bloc_actions_mixin.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

// 定义动作
abstract base class ExampleAction {}

final class ShowTestDialogAction extends ExampleAction {
  final String title;
  final String content;

  ShowTestDialogAction({
    required this.title,
    required this.content,
  });
}

final class ShowSnackbarAction extends ExampleAction {
  final String content;

  ShowSnackbarAction({required this.content});
}

// 定义状态
[@immutable](/user/immutable)
abstract class ExampleState {}

class ExampleInitial extends ExampleState {}

// 创建Cubit并扩展BlocActionsMixin
class ExampleCubit extends Cubit<ExampleState> with BlocActionsMixin<ExampleState, ExampleAction> {
  ExampleCubit() : super(ExampleInitial());

  void onShowTestDialogPressed() {
    addAction(
      ShowTestDialogAction(
        title: 'Test dialog',
        content: "Test dialog message",
      ),
    );
  }

  void onShowTestSnackbarPressed() {
    addAction(ShowSnackbarAction(content: "Test snackbar message"));
  }
}

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

class App extends StatelessWidget {
  const App({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return const MaterialApp(home: HomePage());
  }
}

class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      body: BlocProvider(
        create: (_) => ExampleCubit(),
        child: BlocActionListener<ExampleCubit, ExampleAction>(
          listener: (context, action) {
            if (action is ShowTestDialogAction) {
              final title = action.title;
              final content = action.content;
              showDialog(
                context: context,
                builder: (context) => AlertDialog(
                  title: Text(title),
                  content: Text(content),
                ),
              );
            }
            if (action is ShowSnackbarAction) {
              final content = action.content;
              ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(content)));
            }
          },
          child: Builder(builder: (context) {
            final cubit = context.read<ExampleCubit>();
            return Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Container(
                  width: double.infinity,
                  padding: const EdgeInsets.symmetric(horizontal: 24),
                  child: ElevatedButton(
                    onPressed: cubit.onShowTestDialogPressed,
                    child: const Text("Show test dialog"),
                  ),
                ),
                const SizedBox(height: 16),
                Container(
                  padding: const EdgeInsets.symmetric(horizontal: 24),
                  width: double.infinity,
                  child: ElevatedButton(
                    onPressed: cubit.onShowTestSnackbarPressed,
                    child: const Text("Show test snackbar"),
                  ),
                ),
              ],
            );
          }),
        ),
      ),
    );
  }
}

更多关于Flutter事件监听插件bloc_action_listener的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter事件监听插件bloc_action_listener的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter项目中使用bloc_action_listener插件进行事件监听的代码示例。bloc_action_listener是一个用于监听Bloc事件并响应的Flutter插件。虽然这不是一个广泛知名的库(可能是一个假设的或者自定义的库,因为flutter_bloc是处理Bloc状态管理的官方库),但我们可以假设它提供了类似的功能。以下示例将展示如何设置一个自定义的事件监听器,类似于你提到的bloc_action_listener的功能。

首先,确保你的Flutter项目已经添加了flutter_bloc依赖。如果你正在使用bloc_action_listener,请按照其文档添加相应的依赖。

pubspec.yaml中添加依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_bloc: ^8.0.0  # 请根据需要调整版本号

然后运行flutter pub get来获取依赖。

接下来,我们将创建一个简单的Bloc,一个事件监听器,并在UI中使用它。

1. 创建CounterEvent和CounterState

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

2. 创建CounterBloc

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

class CounterBloc extends Bloc<CounterEvent, CounterState> {
  CounterBloc() : super(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);
    }
  }
}

3. 创建事件监听器(模拟bloc_action_listener)

为了模拟bloc_action_listener的功能,我们可以创建一个Widget来监听Bloc事件并执行动作。

// event_listener.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'counter_event.dart';

class EventListener<T extends Cubit<S>, S> extends StatelessWidget {
  final Widget child;
  final void Function(T cubit, S state, Object? event) onEvent;

  const EventListener({
    required this.child,
    required this.onEvent,
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BlocListener<T, S>(
      listener: (context, state) {
        // 由于我们无法直接获取事件,这里假设我们通过某种方式(如BlocDelegate)捕获事件
        // 这里仅作为示例,我们模拟一个事件处理
        // 实际上,你可能需要在BlocDelegate中重写onEvent方法来捕获事件
        // 然后在这里调用onEvent回调
        // 但由于这是示例,我们直接调用onEvent回调,传递一个模拟事件
        onEvent(context.read<T>(), state, IncrementEvent()); // 示例事件
      },
      child: child,
    );
  }
}

注意:上面的EventListener实际上并不能直接监听事件,因为BlocListener只提供了对状态变化的监听。为了真正监听事件,你可能需要实现一个自定义的BlocDelegate。但为了简化示例,这里我们模拟了一个事件处理。

4. 使用EventListener和CounterBloc

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Flutter Bloc Event Listener Demo')),
        body: BlocProvider(
          create: (_) => CounterBloc(),
          child: EventListener<CounterBloc, CounterState>(
            onEvent: (bloc, state, event) {
              // 在这里处理事件
              print('Event: $event, State: $state');
              if (event is IncrementEvent) {
                print('Incremented!');
              } else if (event is DecrementEvent) {
                print('Decremented!');
              }
            },
            child: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text('${context.select((CounterBloc bloc) => bloc.state.count)}'),
                  ElevatedButton(
                    onPressed: () => context.read<CounterBloc>().add(IncrementEvent()),
                    child: Text('Increment'),
                  ),
                  ElevatedButton(
                    onPressed: () => context.read<CounterBloc>().add(DecrementEvent()),
                    child: Text('Decrement'),
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}

在这个示例中,我们创建了一个简单的计数器Bloc,并尝试模拟了一个事件监听器。然而,由于BlocListener不直接支持事件监听,我们使用了BlocDelegate的概念来解释如何可能实现这一功能(尽管实际代码没有实现自定义的BlocDelegate)。在实际应用中,如果你需要监听Bloc事件,你可能需要查看flutter_bloc的文档,了解如何扩展或自定义Bloc的行为来满足你的需求。

回到顶部