使用 RxJava 进行电子邮件登录验证,可观察对象发出两次

2024-03-14

我正在制作一个简单的登录表单(电子邮件和密码)来尝试增强我的反应式编程技能。我在让电子邮件字段验证按照我想要的方式工作时遇到一些问题。

这是我的代码:

    final Observable<CharSequence> email = RxTextView.textChanges(emailView);

    Observable<Boolean> emailIsValid = email.map(new Func1<CharSequence, Boolean>() {
        @Override
        public Boolean call(CharSequence charSequence) {
            Log.d("asdf", "emailIsValid call: " + charSequence);
            return Pattern.matches(Patterns.EMAIL_ADDRESS.pattern(), charSequence);
        }
    });
    RxView.focusChanges(emailView)
            .withLatestFrom(emailIsValid, new Func2<Boolean, Boolean, Boolean>() {
                @Override
                public Boolean call(Boolean hasFocus, Boolean emailIsValid) {
                    return (!hasFocus && !emailIsValid);
                }
            })
            .subscribe(new Action1<Boolean>() {
                @Override
                public void call(Boolean showError) {
                    if (showError) {
                        emailInputLayout.setError("Enter a valid email");
                    } else {
                        emailInputLayout.setError(null);
                    }
                }
            });
    Observable<CharSequence> password = RxTextView.textChanges(passwordView);

    Observable.combineLatest(emailIsValid, password,
            new Func2<Boolean, CharSequence, Boolean>() {
                @Override
                public Boolean call(Boolean emailIsValid, CharSequence password) {
                    Log.d("asdf", "valid: " + emailIsValid + ", password: " + password);
                    return (emailIsValid && password.length() > 0);
                }
            })
            .subscribe(RxView.enabled(loginButton));

这是日志:

emailIsValid call: emailIsValid call: valid: false, password: // I type 'j' emailIsValid call: j emailIsValid call: j valid: false, password: // I type 'a' emailIsValid call: ja emailIsValid call: ja valid: false, password:

如你看到的,emailIsValid每次我键入一个字符时都会调用两次,这意味着它会执行两次正则表达式匹配,这有点浪费。

我查了一下如何制作emailIsValid每次更改只调用一次,无论有多少订阅者,我发现share()方法。这是我添加时发生的情况.share()到最后emailIsValid的声明:

emailIsValid call: // I type 'j' emailIsValid call: j valid: false, password: // I type 'a' emailIsValid call: ja valid: false, password:

这解决了问题,但它导致了另一个问题:没有初始发射emailIsValid to the combineLatest函数位于最后,因此登录按钮开始启用,而实际上它应该被禁用(变灰)。

解决这个问题最干净的方法是什么?我think我希望它表现得像BehaviorSubject,但我不确定这是否是最好的方法。


I think这里发生的事情如下:

  • 首先subscribe- 末尾的那个RxView.focusChange()...- 导致订阅emailIsValid(因此也为了email).

  • email然后将立即发出当前内容TextView作为其第一项,依次经过emailIsValid and share然后到第一个Subscriber(即withLatestFrom操作员)。

  • 一段时间后combineLatest导致另一个订阅emailIsValid. Since emailIsValid is shared、此订阅不会“通过”email因此每个项目仍然只会被发射一次。

  • 现在的问题是share行为就像PublishSubject: 就是发出来的任何未来向所有订阅者发送事件,但它不会重播任何过去的事件。

总而言之,这意味着:当第二个Subscriber (the combineLatest) 到达时,初始值已经过去 - 它是在第一次订阅后立即发出的。并且只有当你change的内容TextView.

解决方案: Try replay(1).refCount()代替share()在......的最后emailIsValid- 这应该确保每个新的订阅者也收到最近的评估结果以及所有未来的评估结果。

我希望这能解决问题并且我的解释有意义。

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

使用 RxJava 进行电子邮件登录验证,可观察对象发出两次 的相关文章

随机推荐

  • 如何解决此 TypeORM 错误“EntityRepository 已弃用,请改用 Repository.extend 函数”?

    但是 我在 Repository 类中找不到任何 Repository extend 方法 文档中也没有任何相关内容 怎么解决这个问题呢 类型版本 0 3 0 我正在使用 Nest js 并尝试创建自定义存储库 首先 npm install
  • PHPExcel $objWriter->save() 失败

    我正在使用 PHPExcel 根据数据库中的记录创建一个 Excel 文件 在大型数据集上生成它时遇到一个奇怪的问题 我已将其范围缩小到一个引起问题的行 objWriter gt save php output 它只是输出一个空白文件而不是
  • PHP 中如何存储持久数据库连接?

    如文档中所述sqlite popen http de php net manual en function sqlite popen phpphp 尝试利用持久资源机制 哪里详细描述了这个机制 是否可以查看当前存储 使用的所有资源 是否可以
  • 在哪里放置不同测试类的通用设置代码?

    我有几个不同的测试类 它们要求在运行这些测试之前创建某些对象 现在我想知道是否应该将对象初始化代码放入单独的帮助器类或超类中 这样做肯定会减少我的测试类中重复代码的数量 但也会降低它们的可读性 是否有如何处理单元测试的常见设置代码的指南或模
  • 存储缓冲区是否保存现代 x86 上的物理地址或虚拟地址?

    现代 Intel 和 AMD 芯片大存储缓冲区 https stackoverflow com a 54880249 149138在提交到 L1 缓存之前缓冲存储 从概念上讲 这些条目保存存储数据和存储地址 对于地址部分 这些缓冲区条目是否
  • GtKGLArea 无法创建 OpenGL 2.1 上下文

    我目前正在为我的游戏引擎项目开发一个简单的编辑器 虽然该项目似乎在我的主工作站 支持 OpenGL 3 3 的 GTX 650Ti 上运行得很好 但当我在我的设备上测试它时 它似乎被破坏了 测试桌面 GMA4500 最大支持 OpenGL
  • 无法让 GLFW 链接

    我正在尝试编译以下测试程序 include
  • jquery 使用变量中的名称按类选择元素

    我想在 jQuery 中对与某个类名匹配的所有元素执行一些操作 类名来自变量 如何使用我的变量按类进行选择 var x this attr href slice 1 这将设置x等于的名称class I want 现在我想选择具有该类名的所有
  • Sublime Text 3 中的 React.js 文件语法

    我使用 Sublime Text 3 作为我的代码编辑器 我在 React 中编写了一个基本的 hello world 示例 但是代码上的着色不正确 我尝试安装 Babel 插件 但即使在那之后 着色似乎也不起作用 如下图所示 仅仅安装它是
  • 扩展“Prettier - Code Formatter”无法格式化 - (Mac v8.0)

    Prettier 遇到无法格式化的问题 我选择了保存格式 默认格式设置为使用 Prettier 昨天工作正常 现在保存时或运行格式文档命令时没有格式化 没有更改任何设置 我确实尝试卸载并重新安装 Prettier 强制格式化文档也会返回错误
  • 如何在通用 Windows 应用程序中使用 System.Net.Http.HttpClient 忽略自签名证书

    我正在创建一个可移植类库 这意味着据我所知 我必须使用 System Net Http HttpClient 来调用我的 Web API 挑战在于 对于我的通用 Windows 应用程序 我无法弄清楚如何忽略由于 API 服务器可以拥有自签
  • Swift 中的二进制到十六进制

    我有一个二进制字符串 例如 00100100 我想要十六进制字符串 例如 24 Swift 中是否有一种将二进制转换为十六进制的方法 一个可能的解决方案 func binToHex bin String gt String binary t
  • 打印 java scriptlet 变量,就好像它是 JavaScript 变量一样

    你好 我需要在jsp内的标签内的javascript调用内输出一个java变量 例如
  • 启动时依赖 CLR 的程序集解析

    当程序启动时 CLR 是否尝试解析 不一定加载 所有依赖程序集 也就是说 依赖的大会决议是按需完成的吗 请注意 我不是在谈论 Assembly Load Reflective 类型的负载 JIT 编译器负责指导程序集的加载 以响应将 IL
  • 如何在 Blazor 中订阅 onscroll 事件?

    我试图对 Blazor 中的 onscroll 事件做出反应 以便在用户向下滚动网页时为图像设置动画 类似于此网站上的品牌徽标 https lebenswelten stgabriel at https lebenswelten stgab
  • 拖动按钮时 ScrollView 不滚动

    我有一个滚动视图 当它上面没有按钮时 它会滚动 现在确实如此 当拖动鼠标 在模拟器上 时 什么也没有发生 我认为是因为按钮被按下 我怎样才能做到这一点 发生这种情况是因为UIButton的子视图UIScrollView 我假设按钮在您的情况
  • 如何将原始 SQL 查询放入 Sequel 中

    我正在尝试将 SQL 代码转换为 Seqel 以从我的脚本运行它 我如何转换这个 select code count 1 as total from school districts group by code order by total
  • 从 SQL Server 中的 XML 选择空值

    我正在尝试从具有 null 作为属性之一的 XML 中进行选择 它没有返回 null 而是返回 0 我做错了什么 请参阅下面的代码进行复制 declare a xml select a
  • 将变量传递给jsp

    我有一个java类 public void doView RenderRequest renderRequest RenderResponse renderResponse throws IOException PortletExcepti
  • 使用 RxJava 进行电子邮件登录验证,可观察对象发出两次

    我正在制作一个简单的登录表单 电子邮件和密码 来尝试增强我的反应式编程技能 我在让电子邮件字段验证按照我想要的方式工作时遇到一些问题 这是我的代码 final Observable