从多个小部件访问 StreamController Stream

Posted

技术标签:

【中文标题】从多个小部件访问 StreamController Stream【英文标题】:Access StreamController Stream from multiple widgets 【发布时间】:2020-10-25 04:13:50 【问题描述】:

您好,我是 Flutter 和 Streams、BLoC 和提供程序的新手。

我正在尝试从两个不同的小部件访问流。虽然它适用于一个小部件,但它不适用于另一个小部件。我在两个小部件中都有单独的流构建器,我认为这可能是问题所在。为什么它不起作用?我做错了什么而不理解?

带有流控制器和流的 BloC:

String dialCode = "";

class LogInController 
  final dialCodeStreamController = StreamController<String>();
  Stream<String> get dialCodeStream => dialCodeStreamController.stream;

  final dialCodeUpdateStreamController = StreamController<String>();
  Sink<String> get dialCodeSink => dialCodeUpdateStreamController.sink;
  Stream<String> get dialCodeUpdateStream =>
      dialCodeUpdateStreamController.stream;

  LogInController() 
    dialCodeUpdateStream.listen((updatedDialCode) 
      dialCode = updatedDialCode;
      dialCodeStreamController.add(dialCode);
    );
  

  void dispose() 
    dialCodeStreamController.close();
    dialCodeUpdateStreamController.close();
  

流工作的小部件:

class CountryCodeWidget extends StatelessWidget 


final LogInController controller = LogInController();
  @override
  Widget build(BuildContext context) 
    return Container(
      margin: const EdgeInsets.fromLTRB(12, 12, 12, 8),
      child: Card(
        child: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Row(
            mainAxisSize: MainAxisSize.max,
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: <Widget>[
              Text(
                selectCountryCodeString,
                style: hintTextStyle,
              ),
              StreamBuilder<String>(
                  stream: controller.dialCodeStream,
                  initialData: "",
                  builder: (context, snapshot) 
                    return Container(
                      decoration: BoxDecoration(
                        border: Border(
                          bottom: BorderSide(
                            color: snapshot.data == ""
                                ? whiteColor
                                : secondaryColor,
                            width: 4,
                          ),
                        ),
                      ),
                      child: Padding(
                        padding: const EdgeInsets.all(4.0),
                        child: Text(
                          '$snapshot.data',
                          style: textStyle,
                        ),
                      ),
                    );
                  ),
              FlatButton(
                color: secondaryColor,
                child: Icon(
                  Icons.keyboard_arrow_down,
                  color: textColor,
                ),
                onPressed: () => countryCodeDialog(context),
              ),
            ],
          ),
        ),
      ),
    );
  

流不工作的小部件:

class MobileNumberWidget extends StatelessWidget 
  final LogInController controller = LogInController();
  final mobileNumberController = TextEditingController();
  @override
  Widget build(BuildContext context) 
    return Container(
      margin: const EdgeInsets.fromLTRB(12, 0, 12, 8),
      child: Card(
        child: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Row(
            mainAxisSize: MainAxisSize.max,
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: <Widget>[
              Expanded(
                child: Padding(
                  padding: const EdgeInsets.all(4.0),
                  child: TextField(
                    controller: mobileNumberController,
                    keyboardType: TextInputType.phone,
                    style: textStyle,
                    decoration: InputDecoration(
                      hintText: mobileNumberHintString,
                      hintStyle: hintTextStyle,
                      enabledBorder: UnderlineInputBorder(
                        borderSide: BorderSide(
                          color: hintTextColor,
                          width: 1,
                        ),
                      ),
                      focusedBorder: UnderlineInputBorder(
                        borderSide: BorderSide(
                          color: textColor,
                          width: 2,
                        ),
                      ),
                    ),
                  ),
                ),
              ),
              StreamBuilder<String>(
                  stream: controller.dialCodeStream,
                  initialData: "",
                  builder: (context, snapshot) 
                    return FlatButton(
                      child: Icon(
                        Icons.done,
                        color: textColor,
                      ),
                      onPressed: () => mobileNumberController.text.length == 10
                          ? snapshot.data == ""
                              ? showSnackBar(
                                  context, selectCountryCodeSnackBarString)
                              : //sendOTP(mobileNumberController.text)
                              showSnackBar(context, "YEs")
                          : showSnackBar(context, mobileNumberLengthString),
                    );
                  ),
            ],
          ),
        ),
      ),
    );
  

如果我能更好地解释我的问题,或者我是否没有意义,请告诉我。谢谢。

【问题讨论】:

是的,您已经创建了控制器的两个实例。我建议你使用flutter_bloc 库,它完全消除了处理所有这些的开销,而且你增加了代码的可读性。 我可以使用 flutter_bloc、scoped_model 或提供程序库,但我想自己尝试而不是依赖第三方库。我尝试广播流控制器,但它似乎不起作用。有很多解决方法,但我想尝试使这项工作。还是谢谢! 【参考方案1】:

找到问题和解决方案。两次初始化流控制器是问题所在。我在父小部件中初始化并将其传递给子小部件。

【讨论】:

你试过 StreamController.Broadcast 吗?创建一个可以被多个小部件监听的流

以上是关于从多个小部件访问 StreamController Stream的主要内容,如果未能解决你的问题,请参考以下文章

为啥我们必须从一个小部件更新多个小部件?

如何从有状态小部件类 Flutter 访问小部件状态

从 Window* 访问小部件

如何从另一个类访问小部件

iOS8 - 多个目标的单个小部件

按名称从其父级访问 Gtk3 小部件