使用 Inherited Widget 时如何处理 bloc?
How to dispose bloc when using Inherited Widget?
我使用 bloc
和 InheritedWidget
制作了一个简单的应用程序。
以下是代码
class Bloc {
final StreamController<bool> _changeColor = PublishSubject<bool>();
Function(bool) get changeColour => _changeColor.sink.add;
Stream<bool> get colour => _changeColor.stream;
void dispose(){
_changeColor.close();
}
}
class Provider extends InheritedWidget {
final bloc = Bloc();
Provider({Key key,Widget child}): super(key: key,child: child);
@override
bool updateShouldNotify(InheritedWidget oldWidget) {
return true;
}
static Bloc of(BuildContext context){
return (context.inheritFromWidgetOfExactType(Provider) as Provider).bloc;
}
void dispose(){
bloc?.dispose();
}
}
class _HomePageState extends State<HomePage> {
var bloc;
@override
void initState() {
super.initState();
bloc = Provider.of(context);
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
RaisedButton(
onPressed: () {
bloc.changeColour(true);
},
child: Text("Change colour"),
),
StreamBuilder(
builder: (context, snapshot) {
var bool = snapshot?.data ?? false;
return Text(
"First text",
style:
TextStyle(color: bool ? Colors.red : Colors.green),
);
},
stream: bloc?.colour,
),
],
);
}
@override
void dispose() {
super.dispose();
}
}
我不明白在使用 InheritedWidget
时如何调用 bloc 的 dispose 方法。当然,我可以创建一个 bloc 的全局变量,并避免使用 InheritedWidget
使用 bloc 中存在的 dispose 方法来处理 bloc 但我真的想使用 InheritedWidget
.
使用 rxdart
中的 PublishSubject
是否会自动处理 streamcontroller
,它是否具有生命周期意识,我在文档中找不到与此相关的任何内容。是否有任何调试过程来确保 streamcontroller
被正确处理?
使用 Inheritedwidget
是不可能的。小部件不是用来处理数据的,而是用来共享数据的。
您必须将 Inheritedwidget
包装到 StatefulWidget
中并使用后者的处置
添加到 Remi 的答案中,代码看起来像这样
import 'package:flutter/material.dart';
abstract class BlocBase {
void dispose();
}
class BlocProvider<T extends BlocBase> extends StatefulWidget {
BlocProvider({
Key key,
@required this.child,
@required this.bloc,
}): super(key: key);
final T bloc;
final Widget child;
@override
_BlocProviderState<T> createState() => _BlocProviderState<T>();
static T of<T extends BlocBase>(BuildContext context){
final type = _typeOf<BlocProvider<T>>();
BlocProvider<T> provider = context.ancestorWidgetOfExactType(type);
return provider.bloc;
}
static Type _typeOf<T>() => T;
}
class _BlocProviderState<T> extends State<BlocProvider<BlocBase>>{
@override
void dispose(){
widget.bloc.dispose();
super.dispose();
}
@override
Widget build(BuildContext context){
return widget.child;
}
}
class Bloc implements BlocBase {
final StreamController<bool> _changeColor = PublishSubject<bool>();
Function(bool) get changeColour => _changeColor.sink.add;
Stream<bool> get colour => _changeColor.stream;
@override
void dispose() {
_changeColor.close();
}
}
class _HomePageState extends State<HomePage> {
Bloc bloc;
var colour = false;
@override
void initState() {
super.initState();
bloc = BlocProvider.of<Bloc>(context);
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
RaisedButton(
onPressed: () {
if (colour) {
bloc.changeColour(false);
colour = false;
} else {
bloc.changeColour(true);
colour = true;
}
},
child: Text("Change colour"),
),
StreamBuilder(
builder: (context, snapshot) {
var bool = snapshot?.data ?? false;
return Text(
"First text",
style: TextStyle(color: bool ? Colors.red : Colors.green),
);
},
stream: bloc?.colour,
),
],
);
}
@override
void dispose() {
print("Bloc is disposed");
bloc.dispose();
super.dispose();
}
}
我使用 bloc
和 InheritedWidget
制作了一个简单的应用程序。
以下是代码
class Bloc {
final StreamController<bool> _changeColor = PublishSubject<bool>();
Function(bool) get changeColour => _changeColor.sink.add;
Stream<bool> get colour => _changeColor.stream;
void dispose(){
_changeColor.close();
}
}
class Provider extends InheritedWidget {
final bloc = Bloc();
Provider({Key key,Widget child}): super(key: key,child: child);
@override
bool updateShouldNotify(InheritedWidget oldWidget) {
return true;
}
static Bloc of(BuildContext context){
return (context.inheritFromWidgetOfExactType(Provider) as Provider).bloc;
}
void dispose(){
bloc?.dispose();
}
}
class _HomePageState extends State<HomePage> {
var bloc;
@override
void initState() {
super.initState();
bloc = Provider.of(context);
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
RaisedButton(
onPressed: () {
bloc.changeColour(true);
},
child: Text("Change colour"),
),
StreamBuilder(
builder: (context, snapshot) {
var bool = snapshot?.data ?? false;
return Text(
"First text",
style:
TextStyle(color: bool ? Colors.red : Colors.green),
);
},
stream: bloc?.colour,
),
],
);
}
@override
void dispose() {
super.dispose();
}
}
我不明白在使用 InheritedWidget
时如何调用 bloc 的 dispose 方法。当然,我可以创建一个 bloc 的全局变量,并避免使用 InheritedWidget
使用 bloc 中存在的 dispose 方法来处理 bloc 但我真的想使用 InheritedWidget
.
使用 rxdart
中的 PublishSubject
是否会自动处理 streamcontroller
,它是否具有生命周期意识,我在文档中找不到与此相关的任何内容。是否有任何调试过程来确保 streamcontroller
被正确处理?
使用 Inheritedwidget
是不可能的。小部件不是用来处理数据的,而是用来共享数据的。
您必须将 Inheritedwidget
包装到 StatefulWidget
中并使用后者的处置
添加到 Remi 的答案中,代码看起来像这样
import 'package:flutter/material.dart';
abstract class BlocBase {
void dispose();
}
class BlocProvider<T extends BlocBase> extends StatefulWidget {
BlocProvider({
Key key,
@required this.child,
@required this.bloc,
}): super(key: key);
final T bloc;
final Widget child;
@override
_BlocProviderState<T> createState() => _BlocProviderState<T>();
static T of<T extends BlocBase>(BuildContext context){
final type = _typeOf<BlocProvider<T>>();
BlocProvider<T> provider = context.ancestorWidgetOfExactType(type);
return provider.bloc;
}
static Type _typeOf<T>() => T;
}
class _BlocProviderState<T> extends State<BlocProvider<BlocBase>>{
@override
void dispose(){
widget.bloc.dispose();
super.dispose();
}
@override
Widget build(BuildContext context){
return widget.child;
}
}
class Bloc implements BlocBase {
final StreamController<bool> _changeColor = PublishSubject<bool>();
Function(bool) get changeColour => _changeColor.sink.add;
Stream<bool> get colour => _changeColor.stream;
@override
void dispose() {
_changeColor.close();
}
}
class _HomePageState extends State<HomePage> {
Bloc bloc;
var colour = false;
@override
void initState() {
super.initState();
bloc = BlocProvider.of<Bloc>(context);
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
RaisedButton(
onPressed: () {
if (colour) {
bloc.changeColour(false);
colour = false;
} else {
bloc.changeColour(true);
colour = true;
}
},
child: Text("Change colour"),
),
StreamBuilder(
builder: (context, snapshot) {
var bool = snapshot?.data ?? false;
return Text(
"First text",
style: TextStyle(color: bool ? Colors.red : Colors.green),
);
},
stream: bloc?.colour,
),
],
);
}
@override
void dispose() {
print("Bloc is disposed");
bloc.dispose();
super.dispose();
}
}