Last active
November 17, 2020 07:53
-
-
Save zs-dima/d63c9234612cb4c639add95fd7b23bd6 to your computer and use it in GitHub Desktop.
BlocLifecycle
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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