为什么 trySend 会发出假数据?

2023-12-12

我需要在 MVVM 中获取用户身份验证状态。在存储库中我这样做:

override fun getAuthResponse() = callbackFlow  {
    val listener = AuthStateListener {
        Log.d(TAG, "currentUser: " + (currentUser == null)) //Line2
        trySend(it.currentUser == null)
    }
    auth.addAuthStateListener(listener)
    awaitClose {
        auth.removeAuthStateListener(listener)
    }
}

“Line2”将始终打印true因为用户没有经过身份验证。然后在 ViewModel 中我有:

fun getAuthResponse() = repo.getAuthResponse()

以及内部活动:

setContent {
    //...
    val response = viewModel.getAuthResponse().collectAsState(initial = false).value
    Log.d(TAG, "response: $response") //Line1
}

由于 setContent 是一个可组合函数,因此当我打开应用程序时,它会触发两次。这意味着“Line1”处的日志语句被触发两次。当它第一次点火时,我得到:

response: false
currentUser: true

因此,即使我在前一行调用了 getAuthResponse(),响应也会在之前打印。问题是,由于某种原因,即使当前用户为空,我也会在活动中打印出该用户不为空。当它第二次触发时,我得到了正确的数据:

response: true
currentUser: true

为什么我得到一个非空的用户对象? trySend 会发出假数据吗?


这里的问题是流在设计上是异步的。即使你期望AuthStateListener注册后立即调用,该流程最初仍然没有任何值。collectAsState()需要一个值,它不能只是空的,因此它要求您提供一个初始值。您提供的false这就是你最初得到的response。然后几乎立即调用侦听器,它发出true进而response更改为true以及。

我们有多种方法可以解决此类问题。例如,我们最初可以显示加载屏幕,直到获得正确的值。在上面的例子中,我们可以得到currentUser直接,不使用侦听器,所以我建议使用StateFlow反而。StateFlow与常规不同Flow因为它能够保持其“当前”值。最简单的是使用MutableStateFlow:

override fun getAuthResponse(): StateFlow<Boolean> {
    val flow = MutableStateFlow(auth.currentUser == null)

    val listener = AuthStateListener {
        Log.d(TAG, "currentUser: " + (currentUser == null)) //Line2
        flow.value = it.currentUser == null
    }
    auth.addAuthStateListener(listener)

    return flow
}

setContent {
    //...
    val response = viewModel.getAuthResponse().collectAsState().value
    Log.d(TAG, "response: $response") //Line1
}

这个解决方案可能不是 100% 正确,因为我无法测试它,但我希望你能明白。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 trySend 会发出假数据? 的相关文章

随机推荐

  • EF Core 5.0 - 更新 ASP.NET Core Web API 中的多对多实体

    EF Core 5 0 引入了多对多关系 我陷入了如何通过我的 asp net api 更新它们的困境 对于一对一和一对多关系 有一个约定 只需添加属性名称后跟 ID public class Blog public int BlogId
  • 找不到或无法加载程序集 mscorlib.dll

    首先 我见过这个问题 虽然问题看起来相似 但其实并不相同 我正在运行一个精简的单声道 没有使用 4 5 配置文件构建 configure with profile4 yes with profile4 5 no 我有一个针对 NET 4 0
  • Groupby 与 TimeGrouper“向后”

    我有一个DataFrame包含时间序列 rng pd date range 2016 06 01 periods 24 7 freq H ones pd Series 1 24 7 rng rdf pd DataFrame a ones 最
  • 从透明形式的图像中删除轮廓

    我正在尝试将窗口形式转换为透明 并使其仅显示一个对象 但它在我的对象周围仍然有一条线 描边 它并不像我想要的那么完美 如何取出线条 笔画 附上图片对比一下 这是我的代码 private void Form1 Load object send
  • 动态分配 UI 权限 WPF [重复]

    这个问题在这里已经有答案了 可能的重复 在代码隐藏中设置 WPF UI 权限 我开始使用 WPF 并希望创建一个应用程序 该应用程序将根据用户 AD 及其角色 自定义 显示 隐藏控件 我设法通过使用继承 MarkupExpension 和
  • 如何将 Eclipse 和 Eclipse 项目指向 Eclipse 中的新 JRE 版本? (不使用JAVA_HOME)

    设置场景 我的系统上有两个版本的 Java 有 32 位版本和 64 位版本 我拥有的另一个版本是 64 位版本的 Eclipse Java EE MyEclipse 32位版本 指的是32位版本的JDK 我现在尝试将 Eclipse 32
  • 当使用浏览器返回时,如何保留 jquery 删除的一些输入文本?

    我对以下页面有一些错误 http jsbin com agedu 带有一些注释的源代码 http jsbin com agedu edit 问题是 当输入内容并执行查询以显示搜索结果时 如果我返回浏览器中的搜索页面 Firefox 3 5
  • rdtscp、rdtsc 之间的区别:内存和 cpuid/rdtsc?

    假设我们尝试使用 tsc 进行性能监控 并且我们希望防止指令重新排序 这些是我们的选择 1 rdtscp是一个序列化调用 它可以防止对 rdtscp 调用进行重新排序 asm volatile rdtscp serializing read
  • Java:如何在抛出异常后继续读取文件

    所以我的教授给我们分配了一个项目 我们必须从文本文件中获取命令并使用它们来驱动程序的流程 这些命令 例如起飞 着陆 装载货物 卸载货物等 旨在模拟类似飞机的物体 有时这些命令执行起来没有意义 例如在飞机飞行时装载货物 因此 为了防止发生类似
  • 是否可以在不使用 EDT 的情况下在 Java Swing 中执行主动渲染?

    我正在考虑使用缓冲策略以及 Javadoc 中描述的以下技术 Main loop while done Prepare for rendering the next frame Render single frame do The foll
  • 我可以使用 Java API 将图像文件存储在 firebase 中吗?

    有没有什么方法可以使用Java api将图像文件存储在firebase中以用于android应用程序 我已阅读此主题我可以使用 Java API 将图像文件存储在 firebase 中吗但仍然没有答案 我知道有一个官方 api 名为 fir
  • TFrecord 比原始 JPEG 图像占用更多空间

    我正在尝试将 Jpeg 图像集转换为 TFrecords 但 TFrecord 文件占用的空间几乎是图像集的 5 倍 经过大量谷歌搜索后 我了解到当 JPEG 被写入 TFrecords 时 它们就不再是 JPEG 了 但是我还没有遇到这个
  • 如何子类化 matplotlib 的图形类?

    我正在尝试向我的图形添加一些自定义行为和属性 但我无法决定有效的 和Pythonic 方法 我的第一个冲动是简单地子类化matplotlib figure Figure但我不知道如何实现这一点 我通常创建新的图形并用类似的东西开始我的绘图
  • .gitattributes:merge=我们的策略与快进合并

    如果我处于这样的 git 情况 da6a750 A Further in A okay for merging back into master bf27b58 Merge branch master into A 86294d1 HEAD
  • 无法使用沙盒帐户

    我真的需要你们的帮助 两个小时以来 我遇到了一个与 Paypal Sandbox 相关的非常奇怪的问题 我在堆栈溢出上阅读了很多答案 但没有一个对我有帮助 我将尝试解释我的问题 当我创建一个新的沙箱帐户 尊重密码强度 负载平衡等所有规则 时
  • 序列化数组以将它们存储在数据库中的意义是什么?

    我看到人们存储数组的方式如下 a 6 i 0 s 5 11148 i 1 s 5 11149 i 2 s 5 11150 i 3 s 5 11153 i 4 s 5 11152 i 5 s 5 11160 为什么他们不能是 11148 11
  • Cython 中数组的总和

    我正在尝试找到使用 Cython 水平求和 numpy 数组数组的最快方法 首先 假设我有一个随机浮点数 10 x 100 000 的二维数组 我可以创建一个object数组 每一列作为数组中的值 如下所示 n 10 5 a np rand
  • 如果名称变量以下划线为前缀,则 Bean 验证不起作用

    我正在尝试一些 bean 验证 但我偶然发现了 奇怪 的行为 我正在使用 Glassfish 和 Primefaces 作为前端 如果有什么区别的话 在我的项目的其他地方 我使用 Hibernate validator 我不确定它是否正在验
  • 垃圾收集器 C#,有关“清除”对象的问题

    我阅读了一些有关垃圾收集的信息 它是如何工作的等 我尝试通过我的示例了解它是如何工作的 但我认为我有问题 我知道垃圾收集器在以下情况下运行 内存不够 你调用GC Collect 这是我的代码 public partial class For
  • 为什么 trySend 会发出假数据?

    我需要在 MVVM 中获取用户身份验证状态 在存储库中我这样做 override fun getAuthResponse callbackFlow val listener AuthStateListener Log d TAG curre