Skip to content

Commit

Permalink
Expose lazy parameter on RepositoryProvider and BlocProvider (#749)
Browse files Browse the repository at this point in the history
  • Loading branch information
felangel committed Dec 28, 2019
1 parent f451e25 commit 0bce32b
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 6 deletions.
2 changes: 1 addition & 1 deletion packages/flutter_bloc/lib/src/bloc_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ typedef BlocBuilderCondition<S> = bool Function(S previous, S current);
///
/// ```dart
/// BlocBuilder<BlocA, BlocAState>(
/// condition: (previousState, state) {
/// condition: (previous, current) {
/// // return true/false to determine whether or not
/// // to rebuild the widget with state
/// },
Expand Down
6 changes: 3 additions & 3 deletions packages/flutter_bloc/lib/src/bloc_listener.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ typedef BlocListenerCondition<S> = bool Function(S previous, S current);
/// ```dart
/// BlocListener<BlocA, BlocAState>(
/// listener: (context, state) {
/// /// do stuff here based on BlocA's state
/// // do stuff here based on BlocA's state
/// },
/// child: Container(),
/// )
Expand All @@ -41,7 +41,7 @@ typedef BlocListenerCondition<S> = bool Function(S previous, S current);
/// BlocListener<BlocA, BlocAState>(
/// bloc: blocA,
/// listener: (context, state) {
/// /// do stuff here based on BlocA's state
/// // do stuff here based on BlocA's state
/// },
/// child: Container(),
/// )
Expand All @@ -58,7 +58,7 @@ typedef BlocListenerCondition<S> = bool Function(S previous, S current);
///
/// ```dart
/// BlocListener<BlocA, BlocAState>(
/// condition: (previousState, state) {
/// condition: (previous, current) {
/// // return true/false to determine whether or not
/// // to invoke listener with state
/// },
Expand Down
11 changes: 10 additions & 1 deletion packages/flutter_bloc/lib/src/bloc_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import 'package:bloc/bloc.dart';
/// It is used as a dependency injection (DI) widget so that a single instance of a [bloc] can be provided
/// to multiple widgets within a subtree.
///
/// Automatically handles closing the [bloc] when used with [create].
/// Automatically handles closing the [bloc] when used with [create]
/// and lazily creates the provided [bloc] unless [lazy] is set to `false`.
///
/// ```dart
/// BlocProvider(
Expand All @@ -24,6 +25,10 @@ class BlocProvider<T extends Bloc<dynamic, dynamic>>
/// [child] and its descendants which will have access to the [bloc].
final Widget child;

/// Whether or not the [bloc] being provided should be lazily created.
/// Defaults to `true`.
final bool lazy;

final Dispose<T> _dispose;

final Create<T> _create;
Expand All @@ -33,11 +38,13 @@ class BlocProvider<T extends Bloc<dynamic, dynamic>>
Key key,
@required Create<T> create,
Widget child,
bool lazy,
}) : this._(
key: key,
create: create,
dispose: (_, bloc) => bloc?.close(),
child: child,
lazy: lazy,
);

/// Takes a [bloc] and a [child] which will have access to the [bloc] via `BlocProvider.of(context)`.
Expand Down Expand Up @@ -70,6 +77,7 @@ class BlocProvider<T extends Bloc<dynamic, dynamic>>
@required Create<T> create,
Dispose<T> dispose,
this.child,
this.lazy,
}) : _create = create,
_dispose = dispose,
super(key: key, child: child);
Expand Down Expand Up @@ -111,6 +119,7 @@ class BlocProvider<T extends Bloc<dynamic, dynamic>>
create: _create,
dispose: _dispose,
child: child,
lazy: lazy,
);
}
}
4 changes: 4 additions & 0 deletions packages/flutter_bloc/lib/src/repository_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import 'package:provider/provider.dart';
/// It is used as a dependency injection (DI) widget so that a single instance of a repository can be provided
/// to multiple widgets within a subtree.
///
/// Lazily creates the provided repository unless [lazy] is set to `false`.
///
/// ```dart
/// RepositoryProvider(
/// create: (context) => RepositoryA(),
Expand All @@ -20,11 +22,13 @@ class RepositoryProvider<T> extends Provider<T> {
Key key,
@required Create<T> create,
Widget child,
bool lazy,
}) : super(
key: key,
create: create,
dispose: (_, __) {},
child: child,
lazy: lazy,
);

/// Takes a repository and a [child] which will have access to the repository.
Expand Down
2 changes: 1 addition & 1 deletion packages/flutter_bloc/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ dependencies:
flutter:
sdk: flutter
bloc: ^3.0.0
provider: ^4.0.0
provider: ^4.0.1

dev_dependencies:
flutter_test:
Expand Down
29 changes: 29 additions & 0 deletions packages/flutter_bloc/test/bloc_provider_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,35 @@ void main() {
expect(tester.takeException(), isInstanceOf<AssertionError>());
});

testWidgets('lazily loads blocs by default', (WidgetTester tester) async {
var createCalled = false;
await tester.pumpWidget(
BlocProvider(
create: (_) {
createCalled = true;
return CounterBloc();
},
child: Container(),
),
);
expect(createCalled, isFalse);
});

testWidgets('can override lazy loading', (WidgetTester tester) async {
var createCalled = false;
await tester.pumpWidget(
BlocProvider(
lazy: false,
create: (_) {
createCalled = true;
return CounterBloc();
},
child: Container(),
),
);
expect(createCalled, isTrue);
});

testWidgets('passes bloc to children', (WidgetTester tester) async {
CounterBloc _create(BuildContext context) => CounterBloc();
final _child = CounterPage();
Expand Down
28 changes: 28 additions & 0 deletions packages/flutter_bloc/test/multi_bloc_provider_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,34 @@ void main() {
expect(counterText.data, '0');
});

testWidgets('adds event to each bloc', (WidgetTester tester) async {
await tester.pumpWidget(
MultiBlocProvider(
providers: [
BlocProvider<CounterBloc>(
create: (context) => CounterBloc()..add(CounterEvent.decrement),
),
BlocProvider<ThemeBloc>(
create: (context) => ThemeBloc()..add(ThemeEvent.toggle),
),
],
child: MyApp(),
),
);

await tester.pump();

final materialApp =
tester.widget(find.byType(MaterialApp)) as MaterialApp;
expect(materialApp.theme, ThemeData.dark());

final counterFinder = find.byKey((Key('counter_text')));
expect(counterFinder, findsOneWidget);

final counterText = tester.widget(counterFinder) as Text;
expect(counterText.data, '-1');
});

testWidgets('close on counter bloc which was loaded (lazily)',
(WidgetTester tester) async {
var counterBlocClosed = false;
Expand Down
30 changes: 30 additions & 0 deletions packages/flutter_bloc/test/repository_provider_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,36 @@ void main() {
expect(tester.takeException(), isInstanceOf<AssertionError>());
});

testWidgets('lazily loads repositories by default',
(WidgetTester tester) async {
var createCalled = false;
await tester.pumpWidget(
RepositoryProvider(
create: (_) {
createCalled = true;
return Repository(0);
},
child: Container(),
),
);
expect(createCalled, isFalse);
});

testWidgets('can override lazy loading', (WidgetTester tester) async {
var createCalled = false;
await tester.pumpWidget(
RepositoryProvider(
create: (_) {
createCalled = true;
return Repository(0);
},
lazy: false,
child: Container(),
),
);
expect(createCalled, isTrue);
});

testWidgets('passes value to children via builder',
(WidgetTester tester) async {
final repository = Repository(0);
Expand Down

0 comments on commit 0bce32b

Please sign in to comment.