Flutter: 如何向现有的Stream添加事件?

huangapple go评论57阅读模式
英文:

Flutter: how do I add event to existing Stream?

问题

I'm using the Stream that is returned by FirebaseAuth.instance.idTokenChanges() in a StreamProvider, to update the whole underlying Widget-tree everytime a user signs up/in/out.

When I update the displayName for example, is there a way I can manually add an event to that Stream, so that the StreamBuidler rebuilds the widget tree with the NEW user data (new displayName), so that the changes display in the UI?

Can I maybe access the controller associated with the stream, so I can call .sink.add() on it? Or is there any other way?

英文:

I'm using the Stream that is returned by FirebaseAuth.instance.idTokenChanges() in a StreamProvider, to update the whole underlying Widget-tree everytime a user signs up/in/out.

When I update the displayName for example, is there a way I can manually add an event to that Stream, so that the StreamBuidler rebuilds the widget tree with the NEW user data (new displayName), so that the changes display in the UI?

Can I maybe access the controller associated with the stream, so I can call .sink.add() on it? Or is there any other way?

答案1

得分: 0

我已经找到了一个解决方案:使用StreamGroup<T>类将两个(或更多)流合并为一个。

重要提示,这来自于Flutter异步包,而不是dart异步:

import 'dart:async'; //async await以及其他...
import 'package:async/async.dart'; //其中包含了StreamGroup
static StreamController&lt;User&gt; _ctrl;
static Future&lt;void&gt; initCombinedStream() async {

  //如果没有下面这行,热重启时会出现错误:"Bad state: Stream has already been listened to.",也可能是由其他原因引起的
  dispose();

  _ctrl = StreamController&lt;User&gt;();

  StreamGroup streamGroup = StreamGroup&lt;User&gt;();
  await streamGroup
    ..add(_ctrl.stream) //当我想要从我的代码更新用户信息时,我使用这个流
    ..add(FirebaseAuth.instance.idTokenChanges()) //正常的Firebase操作...
    ..close();
  _combinedStream = streamGroup.stream;
}

///也会从我的应用程序中最高级别的StatefulWidget的重写dispose()方法中调用此方法
static void dispose() {
  if (_ctrl != null) _ctrl.close();
}

//例如在更新displayName时调用,否则UI中不会更新
static void updateUserStream() {
  await FirebaseAuth.instance.currentUser.reload(); //不需要调用这个,这个User对象已经被更新了
  _ctrl.add(FirebaseAuth.instance.currentUser); 
}
英文:

I have figured out a solution: using the StreamGroup<T> class to combine two (or more) streams into one.

Important, this is from the Flutter async package, not dart async:

import &#39;dart:async&#39;; //async await and all that...
import &#39;package:async/async.dart&#39;; //this contains StreamGroup

...

  static StreamController&lt;User&gt; _ctrl;
  static Future&lt;void&gt; initCombinedStream() async {

    //without the following line, I get this Error on hot restart: &quot;Bad state: Stream has already been listened to.&quot;
    //maybe that error could also be caused by other reasons
    dispose();

    _ctrl = StreamController&lt;User&gt;();

    StreamGroup streamGroup = StreamGroup&lt;User&gt;();
    await streamGroup
      ..add(_ctrl.stream) //I use this stream when I want to update user info from my code
      ..add(FirebaseAuth.instance.idTokenChanges()) //normal firebase stuff...
      ..close();
    _combinedStream = streamGroup.stream;
  }

  ///this is also called from the overridden dispose() method of the highest StatefulWidget in my app
  static void dispose() {
    if (_ctrl != null) _ctrl.close();
  }

  //called when updating displayName for example, otherwise that wouldn&#39;t update in the UI
  static void updateUserStream() {
    await FirebaseAuth.instance.currentUser.reload(); //no need to call this, this User object is already updated
    _ctrl.add(FirebaseAuth.instance.currentUser); 
  }

huangapple
  • 本文由 发表于 2023年2月24日 02:11:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/75548742.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定