I was wondering if anybody knew a way to know when an InheritedWidget was disposed?
The reason of this question is that I am doing some experiments and I am using an
InheritedWidget
behaves the same way as other Widget
do.
Their lifetime is really short: Usually not longer than one build
call.
If you want to store data for longer, InheritedWidget
is not what you want. You'll need a State
for that.
Which also means that ultimately, you can use State
's dispose for your bloc dispose.
class BlocHolder extends StatefulWidget {
final Widget child;
BlocHolder({this.child});
@override
_BlocHolderState createState() => _BlocHolderState();
}
class _BlocHolderState extends State<BlocHolder> {
final _bloc = new MyBloc();
@override
Widget build(BuildContext context) {
return MyInherited(bloc: _bloc, child: widget.child,);
}
@override
void dispose() {
_bloc.dispose();
super.dispose();
}
}
class MyInherited extends InheritedWidget {
final MyBloc bloc;
MyInherited({this.bloc, Widget child}): super(child: child);
@override
bool updateShouldNotify(InheritedWidget oldWidget) {
return oldWidget != this;
}
}
class MyBloc {
void dispose() {
}
}
Inherited widgets behave very much like stateless widgets, which also do not have a dispose
method. Inherited widgets are getting rebuilt frequently, and all the values stored inside of it would be lost (and without a proper updateShouldNotify
implementation, the dependent widget trees will also be rebuilt frequently!).
To solve this problem, you can utilize a StatefulWidget
:
import 'dart:async';
import 'package:flutter/widgets.dart';
class ApplicationProvider extends StatefulWidget {
const ApplicationProvider({Key key, this.child}) : super(key: key);
final Widget child;
@override
State<StatefulWidget> createState() => _ApplicationProviderState();
}
class _ApplicationProviderState extends State<ApplicationProvider> {
final ApplicationBloc bloc = new ApplicationBloc();
@override
void dispose() {
bloc.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return _ApplicationProvider(
bloc: bloc,
child: widget.child,
);
}
}
class _ApplicationProvider extends InheritedWidget {
_ApplicationProvider({
Key key,
this.bloc,
Widget child,
}) : super(key: key, child: child);
final ApplicationBloc bloc;
@override
bool updateShouldNotify(_ApplicationProvider oldWidget) {
return bloc != oldWidget.bloc;
}
}
class ApplicationBloc {
ApplicationBloc of(BuildContext context) {
final _ApplicationProvider provider = context.inheritFromWidgetOfExactType(_ApplicationProvider);
return provider.bloc;
}
int _counter;
StreamController<int> _counterController = new StreamController<int>.broadcast();
Sink get inCounter => _counterController;
Stream<int> get outCounter => _counterController.stream;
ApplicationBloc() {
_counter = 0;
}
void increment() {
_counter++;
inCounter.add(_counter);
}
int get counter => _counter;
void dispose() {
_counterController.close();
}
}