Flutter通知管理插件bloc_notification的使用

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

Flutter通知管理插件bloc_notification的使用

bloc_notification 包提供了一个混合(mixin),用于将响应 Flutter Bloc 发起的操作与状态分离。在使用 Bloc 库时,你可能会发现某些类型的操作需要在 UI 层处理,比如展示对话框或导航到另一个屏幕。当与 BlocListener 一起使用时,管理这些操作及其关联的数据可能会变得繁琐。

例如,如果你在状态中有一个标志变量,用于通知应用显示一个对话框,那么你需要在对话框完成时关闭该标志。虽然这种方法在某些情况下可能是必要的,但为每个操作管理这些标志可能很麻烦。

为了简化这些与 UI 相关的操作的管理,bloc_notification 包提供了一个简单的通知机制,从 Bloc 发起并由 UI 层处理。这些通知不与当前状态绑定,并依赖于简单的流回调机制。这种做法可以帮助减少应用中管理与 UI 相关的操作的复杂性。

要使用 bloc_notification 包,只需导入混合并将其应用于你的 Bloc。然后,你可以像往常一样定义和分发操作,同时在 UI 层通过提供的回调机制单独处理与 UI 相关的操作。

特性

  • BlocNotificationMixin:允许你从 Bloc 向 UI 层发送通知的混合。
  • BlocNotificationListener:监听由 BlocNotificationMixin 发送的通知的组件,它包装了 BlocListener
  • BlocNotificationConsumer:监听由 BlocNotificationMixin 发送的通知的组件,它包装了 BlocConsumer
  • NotificationObserverMixin:可以与 BlocObserver 一起使用的混合,用于额外监听通知。
  • 易于迁移:通过多个混合轻松添加功能,无需扩展。
  • 兼容性:兼容 BlocCubit

使用方法

BlocNotificationMixin

BlocNotificationMixin 提供了一种通过回调机制通知 UI 某些事件的方法。你可以这样使用它:

class MyBloc extends Bloc<MyEvent, MyState> with BlocNotificationMixin<MyState, MyNotification> {

  void performAction() {
    // ...
    // `notify(...)` 来自混合。
    notify(MyNotification());
  }

  [@override](/user/override)
  void onNotification(BlocNotification<MyNotification> blocNotification) {
    // 响应通知
  }
}

MyNotification 类可以是任何数据结构,例如:

abstract class Notification {}

class ShowDialogNotification extends Notification {
  ShowDialogNotification(this.message);

  final String message;
}

class NavigateToPageNotification extends Notification {
  NavigateToPageNotification(this.pageName);

  final String pageName;
}

BlocNotificationListener

BlocNotificationListener 类似于 BlocListener 组件,但它除了监听状态变化外还监听通知。你可以这样使用它:

BlocNotificationListener<CounterCubit, int, PageNotification>(
  notificationListener: (BuildContext context, PageNotification notification) {
    // 在这里处理通知
  },
  child: MyWidget(),
);

BlocNotificationConsumer

BlocNotificationConsumer 类似于 BlocConsumer 组件,但它除了监听状态变化外还监听通知。你可以这样使用它:

BlocNotificationConsumer<CounterCubit, int, PageNotification>(
  notificationListener: (BuildContext context, PageNotification notification) {
    // 处理通知
  },
  builder: (BuildContext context, int state) {
    // 构建你的组件
  },
);

请注意,通知的触发不会导致 UI 的重建。

NotificationObserver

通过与现有的 BlocObserver 混合,可以轻松观察来自 bloc/cubit 的通知:

class MyObserver extends BlocObserver with NotificationObserverMixin{
  
  [@override](/user/override)
  void onNotification(BlocBase bloc, BlocNotification notification) {
    // 处理通知
  }
}

示例代码

以下是完整的示例代码,展示了如何使用 bloc_notification 包:

import 'package:bloc_notification/bloc_notification.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.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: BlocProvider<CounterCubit>(
        create: (context) => CounterCubit(),
        child: const MyHomePage(title: 'Flutter Demo Home Page'),
      ),
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            BlocNotificationConsumer<CounterCubit, int, PageNotification>(
              notificationListener: (context, notification) {
                if (notification is ShowDialogNotification) {
                  showDialog(
                      context: context,
                      builder: (context) {
                        return const AlertDialog(
                          title: Text("This is the dialog"),
                        );
                      });
                }
              },
              builder: (context, state) {
                return Text(
                  "$state",
                  style: Theme.of(context).textTheme.headlineMedium,
                );
              },
            ),
          ],
        ),
      ),
      floatingActionButton: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          FloatingActionButton(
            onPressed: context.read<CounterCubit>().increaseCounter,
            tooltip: 'Increment',
            child: const Icon(Icons.add),
          ),
          FloatingActionButton(
            onPressed: context.read<CounterCubit>().showDialog,
            tooltip: 'Show dialog',
            child: const Icon(Icons.notification_add),
          ),
        ],
      ),
    );
  }
}

abstract class PageNotification {
  const PageNotification();
}

class ShowDialogNotification extends PageNotification {
  const ShowDialogNotification();
}

class CounterCubit extends Cubit<int>
    with BlocNotificationMixin<int, PageNotification> {
  CounterCubit() : super(0);

  void increaseCounter() {
    emit(state + 1);
  }

  void showDialog() {
    notify(const ShowDialogNotification());
  }
}

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

1 回复

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


在Flutter应用中,使用bloc_notification插件可以帮助你更好地管理通知状态。这个插件通常与BLoC(Business Logic Component)架构一起使用,以实现状态管理和业务逻辑的分离。以下是一个简要的代码示例,展示如何在Flutter应用中使用bloc_notification插件。

首先,确保你已经在pubspec.yaml文件中添加了blocflutter_bloc依赖项,以及任何必要的通知管理插件(虽然bloc_notification不是一个广泛认可的官方插件名,这里假设你需要的是与BLoC结合使用的通知管理功能,通常会用到flutter_local_notifications等插件来处理具体的通知功能)。

dependencies:
  flutter:
    sdk: flutter
  flutter_bloc: ^8.0.0
  flutter_local_notifications: ^9.0.0  # 假设这是处理通知的插件

然后,你需要创建BLoC和事件/状态类。这里我们创建一个简单的通知BLoC来管理通知的显示。

1. 定义事件和状态

// notification_event.dart
import 'package:equatable/equatable.dart';

abstract class NotificationEvent extends Equatable {
  const NotificationEvent();

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

class ShowNotificationEvent extends NotificationEvent {
  final String title;
  final String body;

  const ShowNotificationEvent({required this.title, required this.body});

  @override
  List<Object> get props => [title, body];
}
// notification_state.dart
import 'package:equatable/equatable.dart';

abstract class NotificationState extends Equatable {
  const NotificationState();

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

class NotificationUninitialized extends NotificationState {}

class NotificationShown extends NotificationState {
  final String message;

  const NotificationShown({required this.message});

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

2. 创建BLoC

// notification_bloc.dart
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:your_app/notification_event.dart';
import 'package:your_app/notification_state.dart';

class NotificationBloc extends Bloc<NotificationEvent, NotificationState> {
  final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;

  NotificationBloc({required this.flutterLocalNotificationsPlugin})
      : super(NotificationUninitialized()) {
    _configureLocalNotifications();
  }

  Future<void> _configureLocalNotifications() async {
    var initializationSettingsAndroid =
        AndroidInitializationSettings('app_icon');
    var initializationSettingsIOS = IOSInitializationSettings(
      requestAlertPermission: true,
      requestBadgePermission: true,
      requestSoundPermission: true,
    );
    var initializationSettings = InitializationSettings(
      android: initializationSettingsAndroid,
      iOS: initializationSettingsIOS,
    );
    await flutterLocalNotificationsPlugin.initialize(initializationSettings,
        onSelectNotification: (String? payload) async {
      // Handle payload when notification is tapped by user.
    });
  }

  @override
  Stream<NotificationState> mapEventToState(
    NotificationEvent event,
  ) async* {
    if (event is ShowNotificationEvent) {
      var androidPlatformChannelSpecifics = AndroidNotificationDetails(
        'your channel id',
        'your channel name',
        'your channel description',
        importance: Importance.max,
        priority: Priority.high,
      );
      var iOSPlatformChannelSpecifics = IOSNotificationDetails();
      var platformChannelSpecifics = NotificationDetails(
        android: androidPlatformChannelSpecifics,
        iOS: iOSPlatformChannelSpecifics,
      );
      await flutterLocalNotificationsPlugin.show(
        0,
        event.title,
        event.body,
        platformChannelSpecifics,
        payload: 'item x',
      );
      yield NotificationShown(message: 'Notification shown');
    }
  }
}

3. 使用BLoC在UI中显示通知

// main.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:your_app/notification_bloc.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:your_app/notification_event.dart';

void main() {
  final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
      FlutterLocalNotificationsPlugin();
  runApp(
    BlocProvider<NotificationBloc>(
      create: (context) => NotificationBloc(
        flutterLocalNotificationsPlugin: flutterLocalNotificationsPlugin,
      ),
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Notification Demo')),
        body: Center(
          child: NotificationButton(),
        ),
      ),
    );
  }
}

class NotificationButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: () {
        context.read<NotificationBloc>().add(ShowNotificationEvent(
          title: 'Hello',
          body: 'This is a notification!',
        ));
      },
      child: Text('Show Notification'),
    );
  }
}

在这个示例中,我们创建了一个简单的BLoC来管理通知的显示。当用户点击按钮时,会触发一个ShowNotificationEvent事件,BLoC接收到事件后,使用flutter_local_notifications插件显示通知,并更新状态为NotificationShown

请注意,这只是一个基础示例,实际应用中你可能需要处理更多的状态和事件,以及更复杂的通知逻辑。此外,bloc_notification这个名称可能并不是一个具体存在的插件,因此这里使用了flutter_local_notifications作为处理通知的插件。根据你的具体需求,你可能需要调整代码。

回到顶部