LCOV - code coverage report
Current view: top level - src - bloc_selector.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 29 29 100.0 %
Date: 2021-09-21 11:48:43 Functions: 0 0 -

          Line data    Source code
       1             : import 'package:flutter/widgets.dart';
       2             : import 'package:flutter_bloc/flutter_bloc.dart';
       3             : 
       4             : /// Signature for the `selector` function which
       5             : /// is responsible for returning a selected value, [T], based on [state].
       6             : typedef BlocWidgetSelector<S, T> = T Function(S state);
       7             : 
       8             : /// {@template bloc_selector}
       9             : /// [BlocSelector] is analogous to [BlocBuilder] but allows developers to
      10             : /// filter updates by selecting a new value based on the bloc state.
      11             : /// Unnecessary builds are prevented if the selected value does not change.
      12             : ///
      13             : /// **Note**: the selected value must be immutable in order for [BlocSelector]
      14             : /// to accurately determine whether [builder] should be called again.
      15             : ///
      16             : /// ```dart
      17             : /// BlocSelector<BlocA, BlocAState, SelectedState>(
      18             : ///   selector: (state) {
      19             : ///     // return selected state based on the provided state.
      20             : ///   },
      21             : ///   builder: (context, state) {
      22             : ///     // return widget here based on the selected state.
      23             : ///   },
      24             : /// )
      25             : /// ```
      26             : /// {@endtemplate}
      27             : class BlocSelector<B extends BlocBase<S>, S, T> extends StatefulWidget {
      28             :   /// {@macro bloc_selector}
      29           1 :   const BlocSelector({
      30             :     Key? key,
      31             :     required this.selector,
      32             :     required this.builder,
      33             :     this.bloc,
      34           1 :   }) : super(key: key);
      35             : 
      36             :   /// The [bloc] that the [BlocSelector] will interact with.
      37             :   /// If omitted, [BlocSelector] will automatically perform a lookup using
      38             :   /// [BlocProvider] and the current [BuildContext].
      39             :   final B? bloc;
      40             : 
      41             :   /// The [builder] function which will be invoked
      42             :   /// when the selected state changes.
      43             :   /// The [builder] takes the [BuildContext] and selected `state` and
      44             :   /// must return a widget.
      45             :   /// This is analogous to the [builder] function in [BlocBuilder].
      46             :   final BlocWidgetBuilder<T> builder;
      47             : 
      48             :   /// The [selector] function which will be invoked on each widget build
      49             :   /// and is responsible for returning a selected value of type [T] based on
      50             :   /// the current state.
      51             :   final BlocWidgetSelector<S, T> selector;
      52             : 
      53           1 :   @override
      54           1 :   State<BlocSelector<B, S, T>> createState() => _BlocSelectorState<B, S, T>();
      55             : }
      56             : 
      57             : class _BlocSelectorState<B extends BlocBase<S>, S, T>
      58             :     extends State<BlocSelector<B, S, T>> {
      59             :   late B _bloc;
      60             :   late T _state;
      61             : 
      62           1 :   @override
      63             :   void initState() {
      64           1 :     super.initState();
      65           5 :     _bloc = widget.bloc ?? context.read<B>();
      66           5 :     _state = widget.selector(_bloc.state);
      67             :   }
      68             : 
      69           1 :   @override
      70             :   void didUpdateWidget(BlocSelector<B, S, T> oldWidget) {
      71           1 :     super.didUpdateWidget(oldWidget);
      72           3 :     final oldBloc = oldWidget.bloc ?? context.read<B>();
      73           2 :     final currentBloc = widget.bloc ?? oldBloc;
      74           1 :     if (oldBloc != currentBloc) {
      75           1 :       _bloc = currentBloc;
      76           5 :       _state = widget.selector(_bloc.state);
      77             :     }
      78             :   }
      79             : 
      80           1 :   @override
      81             :   void didChangeDependencies() {
      82           1 :     super.didChangeDependencies();
      83           4 :     final bloc = widget.bloc ?? context.read<B>();
      84           2 :     if (_bloc != bloc) {
      85           1 :       _bloc = bloc;
      86           5 :       _state = widget.selector(_bloc.state);
      87             :     }
      88             :   }
      89             : 
      90           1 :   @override
      91             :   Widget build(BuildContext context) {
      92           3 :     if (widget.bloc == null) context.select<B, int>(identityHashCode);
      93           1 :     return BlocListener<B, S>(
      94           1 :       bloc: _bloc,
      95           1 :       listener: (context, state) {
      96           2 :         final selectedState = widget.selector(state);
      97           5 :         if (_state != selectedState) setState(() => _state = selectedState);
      98             :       },
      99           3 :       child: widget.builder(context, _state),
     100             :     );
     101             :   }
     102             : }

Generated by: LCOV version 1.15