【问题标题】:How to dispose bloc when using Inherited Widget?使用 Inherited Widget 时如何处理 bloc?
【发布时间】:2019-06-12 07:55:22
【问题描述】:

我使用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 被正确处理?

【问题讨论】:

    标签: dart flutter bloc inherited-widget


    【解决方案1】:

    使用Inheritedwidget 是不可能的。小部件不是用来处理数据的,而是用来共享数据的。

    您必须将 Inheritedwidget 包装成 StatefulWidget 并使用后者的 dispose

    【讨论】:

    • 我想你指的是你的这个答案stackoverflow.com/questions/51690230/…
    • 现在我更困惑了,所以我应该在涉及 bloc 时将我的 InheritedWidget 包装成 Stateful,对吗?
    • 是的,喜欢我的其他答案
    • 你能看看我发布的答案,只是想知道我的做法是正确的
    • dispose 方法中的 print 语句永远不会被调用
    【解决方案2】:

    添加到 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 已处理");执行了吗?
    猜你喜欢
    • 2018-09-04
    • 2021-08-28
    • 2021-01-27
    • 2019-05-17
    • 2021-04-23
    • 2020-01-17
    • 2019-10-26
    • 2018-12-26
    • 2019-12-13
    相关资源
    最近更新 更多