LCOV - code coverage report
Current view: top level - src - bloc_listener.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 24 24 100.0 %
Date: 2021-07-04 09:18:57 Functions: 0 0 -

          Line data    Source code
       1             : import 'package:flutter/foundation.dart';
       2             : import 'package:flutter/widgets.dart';
       3             : import 'package:flutter_hooks_bloc/src/multi_bloc_listener.dart';
       4             : 
       5             : import 'bloc_hook.dart';
       6             : import 'flutter_bloc.dart' hide BlocProvider;
       7             : 
       8             : /// Signature for the `listener` function which takes the `BuildContext` along
       9             : /// with the `state` and is responsible for executing in response to
      10             : /// `state` changes.
      11             : typedef BlocWidgetListener<S> = void Function(BuildContext context, S state);
      12             : 
      13             : /// Signature for the `listenWhen` function which takes the previous `state`
      14             : /// and the current `state` and is responsible for returning a [bool] which
      15             : /// determines whether or not to call [BlocWidgetListener] of [BlocListener]
      16             : /// with the current `state`.
      17             : typedef BlocListenerCondition<S> = bool Function(S previous, S current);
      18             : 
      19             : /// {@template bloc_listener}
      20             : /// Takes a [BlocWidgetListener] and an optional [bloc] and invokes
      21             : /// the [listener] in response to `state` changes in the [bloc].
      22             : /// It should be used for functionality that needs to occur only in response to
      23             : /// a `state` change such as navigation, showing a `SnackBar`, showing
      24             : /// a `Dialog`, etc...
      25             : /// The [listener] is guaranteed to only be called once for each `state` change
      26             : /// unlike the `builder` in `BlocBuilder`.
      27             : ///
      28             : /// If the [bloc] parameter is omitted, [BlocListener] will automatically
      29             : /// perform a lookup using the current `BuildContext`.
      30             : ///
      31             : /// ```dart
      32             : /// BlocListener<BlocA, BlocAState>(
      33             : ///   listener: (context, state) {
      34             : ///     // do stuff here based on BlocA's state
      35             : ///   },
      36             : ///   child: Container(),
      37             : /// )
      38             : /// ```
      39             : /// Only specify the [bloc] if you wish to provide a [bloc] that is otherwise
      40             : /// not accessible via the current `BuildContext`.
      41             : ///
      42             : /// ```dart
      43             : /// BlocListener<BlocA, BlocAState>(
      44             : ///   bloc: blocA,
      45             : ///   listener: (context, state) {
      46             : ///     // do stuff here based on BlocA's state
      47             : ///   },
      48             : ///   child: Container(),
      49             : /// )
      50             : /// ```
      51             : /// {@endtemplate}
      52             : ///
      53             : /// {@template bloc_listener_listen_when}
      54             : /// An optional [listenWhen] can be implemented for more granular control
      55             : /// over when [listener] is called.
      56             : /// [listenWhen] will be invoked on each [bloc] `state` change.
      57             : /// [listenWhen] takes the previous `state` and current `state` and must
      58             : /// return a [bool] which determines whether or not the [listener] function
      59             : /// will be invoked.
      60             : /// The previous `state` will be initialized to the `state` of the [bloc]
      61             : /// when the [BlocListener] is initialized.
      62             : /// [listenWhen] is optional and if omitted, it will default to `true`.
      63             : ///
      64             : /// ```dart
      65             : /// BlocListener<BlocA, BlocAState>(
      66             : ///   listenWhen: (previous, current) {
      67             : ///     // return true/false to determine whether or not
      68             : ///     // to invoke listener with state
      69             : ///   },
      70             : ///   listener: (context, state) {
      71             : ///     // do stuff here based on BlocA's state
      72             : ///   }
      73             : ///   child: Container(),
      74             : /// )
      75             : /// ```
      76             : /// {@endtemplate}
      77             : class BlocListener<B extends BlocBase<S>, S extends Object>
      78             :     extends BlocListenerBase<B, S> implements NestableBlocListener {
      79             :   /// {@macro bloc_listener}
      80           2 :   const BlocListener({
      81             :     Key? key,
      82             :     B? bloc,
      83             :     BlocListenerCondition<S>? listenWhen,
      84             :     required BlocWidgetListener<S> listener,
      85             :     Widget? child,
      86           2 :   }) : super(
      87             :           key: key,
      88             :           bloc: bloc,
      89             :           listenWhen: listenWhen,
      90             :           listener: listener,
      91             :           child: child,
      92             :         );
      93             : 
      94             :   /// Helps to subscribe to a [bloc]
      95           1 :   @override
      96           1 :   void listen() => $use();
      97             : 
      98           1 :   @override
      99           1 :   bool get hasNoChild => child == null;
     100             : 
     101           2 :   @override
     102             :   DiagnosticsNode asDiagnosticsNode() {
     103           2 :     return DiagnosticsProperty<S>(
     104           4 :       '$runtimeType',
     105           3 :       bloc?.state,
     106             :       ifNull: '',
     107           3 :       showSeparator: bloc?.state != null,
     108             :     );
     109             :   }
     110             : }
     111             : 
     112             : /// {@template bloc_listener_base}
     113             : /// Base class for widgets that listen to state changes in a specified [bloc].
     114             : ///
     115             : /// A [BlocListenerBase] is a [BlocWidget] and maintains the state subscription.
     116             : /// The type of the state and what happens with each state change
     117             : /// is defined by sub-classes.
     118             : /// {@endtemplate}
     119             : abstract class BlocListenerBase<B extends BlocBase<S>, S extends Object>
     120             :     extends BlocWidget<B, S> {
     121             :   /// {@macro bloc_listener_base}
     122           3 :   const BlocListenerBase({
     123             :     Key? key,
     124             :     B? bloc,
     125             :     this.listenWhen,
     126             :     required this.listener,
     127             :     this.child,
     128           3 :   }) : super(key: key, bloc: bloc);
     129             : 
     130             :   /// Takes the previous `state` and the current `state` and is responsible for
     131             :   /// returning a [bool] which determines whether or not to call [listener]
     132             :   /// with the current `state`.
     133             :   final BlocListenerCondition<S>? listenWhen;
     134             : 
     135             :   /// Takes the `BuildContext` along with the [bloc] `state`
     136             :   /// and is responsible for executing in response to `state` changes.
     137             :   final BlocWidgetListener<S> listener;
     138             : 
     139             :   /// The widget which will be rendered as a descendant.
     140             :   final Widget? child;
     141             : 
     142           1 :   @override
     143             :   Widget build(BuildContext context) {
     144           1 :     $use();
     145           1 :     return child!;
     146             :   }
     147             : 
     148           3 :   @override
     149             :   bool onStateEmitted(BuildContext context, S previous, S state) {
     150           5 :     if (listenWhen?.call(previous, state) ?? true) {
     151           6 :       listener.call(context, state);
     152             :     }
     153             :     return false;
     154             :   }
     155             : 
     156           1 :   @override
     157             :   void debugFillProperties(DiagnosticPropertiesBuilder properties) {
     158           1 :     super.debugFillProperties(properties);
     159           2 :     properties.add(DiagnosticsProperty<S>(
     160             :       'state',
     161           2 :       bloc?.state,
     162             :       ifNull: '<null>',
     163           2 :       showSeparator: bloc?.state != null,
     164             :     ));
     165             :   }
     166             : }

Generated by: LCOV version 1.15