如何在使用Inherited Widget时处理bloc的释放?

3

我使用和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方法。当然,我可以创建一个全局变量来避免使用InheritedWidget,并使用bloc中存在的dispose方法来处理bloc的释放,但我真的想使用InheritedWidget

使用rxdart中的PublishSubject是否会自动释放streamcontroller,它是否具有生命周期感知功能,在文档中找不到相关信息。是否有调试过程可以确保正确地释放streamcontroller

2个回答

3

使用 InheritedWidget 不可能实现该功能。该小部件不是用于处理数据,而是用于共享数据。

您需要将您的 InheritedWidget 包装到一个 StatefulWidget 中,并使用后者的 dispose 方法。


1
我认为你指的是你的这个答案:https://dev59.com/HlUK5IYBdhLWcg3wiAUo - BraveEvidence
现在我更加困惑了,所以每当涉及到 bloc 时,我应该将我的 InheritedWidget 包装成 Stateful,是这样吗? - BraveEvidence
是的,像我的其他答案一样。 - Rémi Rousselet
你能否请看一下我发的答案,以便确认我做得是否正确? - BraveEvidence
dispose方法中的打印语句从未被调用。 - BraveEvidence

1
为了补充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();
  }
}

它能工作吗?print("Bloc is disposed"); 被执行了吗? - Pritam Parua

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接