LCOV - code coverage report
Current view: top level - src - bloc_builder.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 32 32 100.0 %
Date: 2021-10-05 22:30:28 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 `builder` function which takes the `BuildContext` and
       5             : /// [state] and is responsible for returning a widget which is to be rendered.
       6             : /// This is analogous to the `builder` function in [StreamBuilder].
       7             : typedef BlocWidgetBuilder<S> = Widget Function(BuildContext context, S state);
       8             : 
       9             : /// Signature for the `buildWhen` function which takes the previous `state` and
      10             : /// the current `state` and is responsible for returning a [bool] which
      11             : /// determines whether to rebuild [BlocBuilder] with the current `state`.
      12             : typedef BlocBuilderCondition<S> = bool Function(S previous, S current);
      13             : 
      14             : /// {@template bloc_builder}
      15             : /// [BlocBuilder] handles building a widget in response to new `states`.
      16             : /// [BlocBuilder] is analogous to [StreamBuilder] but has simplified API to
      17             : /// reduce the amount of boilerplate code needed as well as [bloc]-specific
      18             : /// performance improvements.
      19             : 
      20             : /// Please refer to [BlocListener] if you want to "do" anything in response to
      21             : /// `state` changes such as navigation, showing a dialog, etc...
      22             : ///
      23             : /// If the [bloc] parameter is omitted, [BlocBuilder] will automatically
      24             : /// perform a lookup using [BlocProvider] and the current [BuildContext].
      25             : ///
      26             : /// ```dart
      27             : /// BlocBuilder<BlocA, BlocAState>(
      28             : ///   builder: (context, state) {
      29             : ///   // return widget here based on BlocA's state
      30             : ///   }
      31             : /// )
      32             : /// ```
      33             : ///
      34             : /// Only specify the [bloc] if you wish to provide a [bloc] that is otherwise
      35             : /// not accessible via [BlocProvider] and the current [BuildContext].
      36             : ///
      37             : /// ```dart
      38             : /// BlocBuilder<BlocA, BlocAState>(
      39             : ///   bloc: blocA,
      40             : ///   builder: (context, state) {
      41             : ///   // return widget here based on BlocA's state
      42             : ///   }
      43             : /// )
      44             : /// ```
      45             : /// {@endtemplate}
      46             : ///
      47             : /// {@template bloc_builder_build_when}
      48             : /// An optional [buildWhen] can be implemented for more granular control over
      49             : /// how often [BlocBuilder] rebuilds.
      50             : /// [buildWhen] should only be used for performance optimizations as it
      51             : /// provides no security about the state passed to the [builder] function.
      52             : /// [buildWhen] will be invoked on each [bloc] `state` change.
      53             : /// [buildWhen] takes the previous `state` and current `state` and must
      54             : /// return a [bool] which determines whether or not the [builder] function will
      55             : /// be invoked.
      56             : /// The previous `state` will be initialized to the `state` of the [bloc] when
      57             : /// the [BlocBuilder] is initialized.
      58             : /// [buildWhen] is optional and if omitted, it will default to `true`.
      59             : ///
      60             : /// ```dart
      61             : /// BlocBuilder<BlocA, BlocAState>(
      62             : ///   buildWhen: (previous, current) {
      63             : ///     // return true/false to determine whether or not
      64             : ///     // to rebuild the widget with state
      65             : ///   },
      66             : ///   builder: (context, state) {
      67             : ///     // return widget here based on BlocA's state
      68             : ///   }
      69             : /// )
      70             : /// ```
      71             : /// {@endtemplate}
      72             : class BlocBuilder<B extends BlocBase<S>, S> extends BlocBuilderBase<B, S> {
      73             :   /// {@macro bloc_builder}
      74             :   /// {@macro bloc_builder_build_when}
      75           4 :   const BlocBuilder({
      76             :     Key? key,
      77             :     required this.builder,
      78             :     B? bloc,
      79             :     BlocBuilderCondition<S>? buildWhen,
      80           4 :   }) : super(key: key, bloc: bloc, buildWhen: buildWhen);
      81             : 
      82             :   /// The [builder] function which will be invoked on each widget build.
      83             :   /// The [builder] takes the `BuildContext` and current `state` and
      84             :   /// must return a widget.
      85             :   /// This is analogous to the [builder] function in [StreamBuilder].
      86             :   final BlocWidgetBuilder<S> builder;
      87             : 
      88           4 :   @override
      89           4 :   Widget build(BuildContext context, S state) => builder(context, state);
      90             : }
      91             : 
      92             : /// {@template bloc_builder_base}
      93             : /// Base class for widgets that build themselves based on interaction with
      94             : /// a specified [bloc].
      95             : ///
      96             : /// A [BlocBuilderBase] is stateful and maintains the state of the interaction
      97             : /// so far. The type of the state and how it is updated with each interaction
      98             : /// is defined by sub-classes.
      99             : /// {@endtemplate}
     100             : abstract class BlocBuilderBase<B extends BlocBase<S>, S>
     101             :     extends StatefulWidget {
     102             :   /// {@macro bloc_builder_base}
     103           4 :   const BlocBuilderBase({Key? key, this.bloc, this.buildWhen})
     104           4 :       : super(key: key);
     105             : 
     106             :   /// The [bloc] that the [BlocBuilderBase] will interact with.
     107             :   /// If omitted, [BlocBuilderBase] will automatically perform a lookup using
     108             :   /// [BlocProvider] and the current `BuildContext`.
     109             :   final B? bloc;
     110             : 
     111             :   /// {@macro bloc_builder_build_when}
     112             :   final BlocBuilderCondition<S>? buildWhen;
     113             : 
     114             :   /// Returns a widget based on the `BuildContext` and current [state].
     115             :   Widget build(BuildContext context, S state);
     116             : 
     117           4 :   @override
     118           4 :   State<BlocBuilderBase<B, S>> createState() => _BlocBuilderBaseState<B, S>();
     119             : }
     120             : 
     121             : class _BlocBuilderBaseState<B extends BlocBase<S>, S>
     122             :     extends State<BlocBuilderBase<B, S>> {
     123             :   late B _bloc;
     124             :   late S _state;
     125             : 
     126           4 :   @override
     127             :   void initState() {
     128           4 :     super.initState();
     129          16 :     _bloc = widget.bloc ?? context.read<B>();
     130          12 :     _state = _bloc.state;
     131             :   }
     132             : 
     133           2 :   @override
     134             :   void didUpdateWidget(BlocBuilderBase<B, S> oldWidget) {
     135           2 :     super.didUpdateWidget(oldWidget);
     136           4 :     final oldBloc = oldWidget.bloc ?? context.read<B>();
     137           4 :     final currentBloc = widget.bloc ?? oldBloc;
     138           2 :     if (oldBloc != currentBloc) {
     139           2 :       _bloc = currentBloc;
     140           6 :       _state = _bloc.state;
     141             :     }
     142             :   }
     143             : 
     144           4 :   @override
     145             :   void didChangeDependencies() {
     146           4 :     super.didChangeDependencies();
     147          12 :     final bloc = widget.bloc ?? context.read<B>();
     148           8 :     if (_bloc != bloc) {
     149           1 :       _bloc = bloc;
     150           3 :       _state = _bloc.state;
     151             :     }
     152             :   }
     153             : 
     154           4 :   @override
     155             :   Widget build(BuildContext context) {
     156          10 :     if (widget.bloc == null) context.select<B, int>(identityHashCode);
     157           4 :     return BlocListener<B, S>(
     158           4 :       bloc: _bloc,
     159           8 :       listenWhen: widget.buildWhen,
     160          12 :       listener: (context, state) => setState(() => _state = state),
     161          12 :       child: widget.build(context, _state),
     162             :     );
     163             :   }
     164             : }

Generated by: LCOV version 1.15