Skip to content

Instantly share code, notes, and snippets.

@zs-dima
Last active November 17, 2020 07:53
Show Gist options
  • Save zs-dima/d63c9234612cb4c639add95fd7b23bd6 to your computer and use it in GitHub Desktop.
Save zs-dima/d63c9234612cb4c639add95fd7b23bd6 to your computer and use it in GitHub Desktop.
BlocLifecycle
import 'package:auto_route/auto_route.dart';
import 'package:bloc/bloc.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
extension BlocLifecycleEx on BuildContext {
T bloc<T extends Cubit<Object>>() => BlocLifecycle.of<T>(this);
}
/// Callback when BLoC ready to create
/// [bloc] - previous closed BLoC or null if first create
typedef BlocLifecycleCreate<T> = T Function(
BuildContext context,
T bloc,
);
/// Callback when BLoC ready to close
typedef BlocLifecycleClose<T> = void Function(
BuildContext context,
T bloc,
);
/// Widget is responsible for the life cycle of the block, rebuilding when context is changed.
@immutable
class BlocLifecycle<T extends Cubit<Object>> extends StatefulWidget {
final Widget child;
final BlocLifecycleCreate<T> create;
final BlocLifecycleClose<T> close;
const BlocLifecycle({
@required this.child,
@required this.create,
this.close,
Key key,
}) : assert(child != null, 'Field child in widget BlocLifecycle<T> must not be null'),
assert(create != null, 'Field create in widget BlocLifecycle<T> must not be null'),
super(key: key);
static T of<T extends Cubit<Object>>(BuildContext context) => _BlocLifecycleStateScope.of<T>(context)?.bloc;
@override
State<BlocLifecycle<T>> createState() => _BlocLifecycleState<T>();
}
class _BlocLifecycleState<T extends Cubit<Object>> extends State<BlocLifecycle<T>> {
T bloc;
@override
void didChangeDependencies() {
super.didChangeDependencies();
_closeIfNotNull();
bloc = widget.create(
context,
bloc,
);
}
@override
void dispose() {
_closeIfNotNull();
bloc = null;
super.dispose();
}
void _closeIfNotNull() {
if (bloc != null) {
if (widget.close != null) {
widget.close(
context,
bloc,
);
}
bloc.close();
}
}
@override
Widget build(BuildContext context) => _BlocLifecycleStateScope<T>(
bloc: bloc,
child: widget.child,
);
}
@immutable
class _BlocLifecycleStateScope<T extends Cubit<Object>> extends InheritedWidget {
final T bloc;
const _BlocLifecycleStateScope({
@required Widget child,
@required this.bloc,
Key key,
}) : assert(child != null, 'Field child in widget _BlocLifecycleState must not be null'),
assert(bloc != null, 'Bloc must not be null'),
super(key: key, child: child);
/// Find _BlocLifecycleStateScope in BuildContext
static _BlocLifecycleStateScope of<T extends Cubit<Object>>(BuildContext context) =>
context.dependOnInheritedWidgetOfExactType<_BlocLifecycleStateScope<T>>();
@override
bool updateShouldNotify(_BlocLifecycleStateScope oldWidget) => !identical(bloc, oldWidget.bloc) || bloc != oldWidget.bloc;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment