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

Generated by: LCOV version 1.15