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

Generated by: LCOV version 1.15