浅析RxJava处理复杂表单验证问题的方法

无论是简单的登录页面,还是复杂的订单提交页面,表单的前端验证(比如登录名和密码都符合基本要求才能点亮登录按钮)都是必不可少的步骤。本文展示了如何用RxJava来方便的处理表单提交前的验证问题,例子采用了Android上的一个简单的登录页面

内容提要

传统的验证方式

combineLatest操作符

用combineLatest处理表单验证

combineLatest和zip的区别

本文中所演示的例子sample代码位于RxAndroidDemo,参见loginActivity这个文件

传统的验证方式

这里我们用最简单的例子来说明,如上图,一个email输入和一个password输入,下方是一个登录的按钮。只有当email输入框内容含有@字符,password输入框内容大于4个,才点亮下方的按钮。

首先你用EditText还是继承自EditText的控件,一般来说监听它的内容,都是用addTextChangedListener。但是如何显然登录按钮的enable与否是同时要判断email和password的,两个都成立才可点亮。所以我们在email的TextWatcher中除了要判断email是否符合条件以外,还要同时判断password是否符合条件,这样以来就容易造成多重判断。
试想如果你在提交一个订单的表单,上面是十几个输入框,每个输入的内容都同时符合条件才可以点亮“提交”按钮,这是多么痛苦的事情————每一个输入框的改变都要同时再判断其他十几个输入框内容是否符合(实际上此时其他十几个输入框没变化)

combineLatest操作符

combineLatest是RxJava本身提供的一个常用的操作符,它接受两个或以上的Observable和一个FuncX闭包。当传入的Observable中任意的一个发射数据时,combineLatest将每个Observable的最近值(Lastest)联合起来(combine)传给FuncX闭包进行处理。要点在于

1.combineLatest是会存储每个Observable的最近的值

2.任意一个Observable发射新值时都会触发操作->“combine all the Observable's lastest value together and send to Function”

用combineLatest处理表单验证

首先我们写上email和password的验证方法,一个需要含有@字符,一个要求字符数超过4个:

private boolean isEmailValid(String email) {
  //TODO: Replace this with your own logic
  return email.contains("@");
 }
private boolean isPasswordValid(String password) {
 //TODO: Replace this with your own logic
 return password.length() > 4;
}

随后,我们针对email和password分别创建Observable,发射的值即为各自edittext的变化的内容,而call回调方法的返回值是textWatcher中afterTextChanged方法的传入参数:

Observable<String> ObservableEmail = Observable.create(new Observable.OnSubscribe<String>() {
   @Override
   public void call(final Subscriber<? super String> subscriber) {
    mEmailView.addTextChangedListener(new TextWatcher() {
     @Override
     public void beforeTextChanged(CharSequence s, int start, int count, int after) {
     }
     @Override
     public void onTextChanged(CharSequence s, int start, int before, int count) {
     }
     @Override
     public void afterTextChanged(Editable s) {
      subscriber.onNext(s.toString());
     }
    });
   }
  });
Observable<String> ObservablePassword = Observable.create(new Observable.OnSubscribe<String>() {
 @Override
 public void call(final Subscriber<? super String> subscriber) {
  mPasswordView.addTextChangedListener(new TextWatcher() {
   @Override
   public void beforeTextChanged(CharSequence s, int start, int count, int after) {
   }
   @Override
   public void onTextChanged(CharSequence s, int start, int before, int count) {
   }
   @Override
   public void afterTextChanged(Editable s) {
    subscriber.onNext(s.toString());
   }
  });
 }
});

最后,用combineLastest将ObservableEmail和ObservablePassword联合起来进行验证:

Observable.combineLatest(ObservableEmail, ObservablePassword, new Func2<String, String, Boolean>() {
   @Override
   public Boolean call(String email, String password) {
    return isEmailValid(email) && isPasswordValid(password);
   }
  }).subscribe(new Subscriber<Boolean>() {
   @Override
   public void onCompleted() {
   }
   @Override
   public void onError(Throwable e) {
   }
   @Override
   public void onNext(Boolean verify) {
    if (verify) {
     mEmailSignInButton.setEnabled(true);
    } else {
     mEmailSignInButton.setEnabled(false);
    }
   }
  });

onNext中的verify就是经过combineLastest对两者验证后组合的结果。

参见LoginActivity的bindView()方法

这里,即使表单非常复杂,实际上你需要扩展的话就很容易了:

1.对每个EditText封装一个Observable

2.改写这句话,加入新的逻辑:

return isEmailValid(email) && isPasswordValid(password);

觉得为每一个EditText封装一个Observable要写很多重复代码?放心,Jake Wharton大神早已经想到,RxBinding中的RxTextView就可以解决这个问题:

Observable<CharSequence> ObservableEmail = RxTextView.textChanges(mEmailView);
Observable<CharSequence> ObservablePassword = RxTextView.textChanges(mPasswordView);
Observable.combineLatest(ObservableEmail, ObservablePassword, new Func2<CharSequence, CharSequence, Boolean>() {
 @Override
 public Boolean call(CharSequence email, CharSequence password) {
  return isEmailValid(email.toString()) && isPasswordValid(password.toString());
 }
}).subscribe(new Subscriber<Boolean>() {
 @Override
 public void onCompleted() {
 }
 @Override
 public void onError(Throwable e) {
 }
 @Override
 public void onNext(Boolean verify) {
  if (verify) {
   mEmailSignInButton.setEnabled(true);
  } else {
   mEmailSignInButton.setEnabled(false);
  }
 }
});

参见LoginActivity的bindViewByRxBinding()方法

combineLatest和zip的区别

zip是和combineLatest有点像的一个操作符,接受的参数也是两个或多个Observable和一个闭包。但是区别在于:

1.zip是严格按照顺序来组合每个Observable,比如ObservableA的第一个数据和ObservableB的第一个数据组合在一起发射给FuncX来处理,两者的第N个数据组合在一起发射给FuncX来处理,以此类推.

2.zip并不是任意一个Observable发射数据了就触发闭包处理,而是等待每个Observable的第N个数据都发射齐全了才触发

zip一般用于整合多方按照顺序排列的数据。

以上所述是小编给大家介绍的浅析RxJava处理复杂表单验证问题的方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • RxJava中多种场景的实现总结

    一.推迟执行动作 可以使用timer+map方法实现.代码如下: Observable.timer(5, TimeUnit.MILLISECONDS).map(value->{ return doSomething(); }).subscribe(System.out::println); } 二.推迟发送执行的结果 这种场景要求产生数据的动作是马上执行,但是结果推迟发送.这和上面场景的是不一样的. 这种场景可以使用Observable.zip来实现. zip操作符将多个Observable发射

  • Android中通过RxJava进行响应式程序设计的入门指南

    错误处理 到目前为止,我们都没怎么介绍onComplete()和onError()函数.这两个函数用来通知订阅者,被观察的对象将停止发送数据以及为什么停止(成功的完成或者出错了). 下面的代码展示了怎么使用这两个函数: Observable.just("Hello, world!") .map(s -> potentialException(s)) .map(s -> anotherPotentialException(s)) .subscribe(new Subscrib

  • Android中的Retrofit+OkHttp+RxJava缓存架构使用

    RxJava如何与Retrofit结合 先扔出build.gradle文件的内容 dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.2.0' compile 'io.reactivex:rxjava:1.1.0' compile 'io.reactivex:rxand

  • RxJava两步打造华丽的Android引导页

    前言 之前的一篇文章:基于RxJava实现酷炫启动页 中,我们尝试了用RxJava实现酷炫的启动页,今天我们在此基础上加入首次使用APP时的引导页功能. 效果如下图: 思路:思路其实很简单,就是在WelcomeActivity 中setContentView()之前判断是否是首次打开APP,若是,则去启动引导页(WelcomeGuideActivity)并return:若不是,则直接setContentView(),然后启动动画再启动MainActivity. 一.WelcomeActivity

  • 基于RxJava实现酷炫启动页

    前言 RxJava 在 GitHub 主页上的自我介绍是 "a library for composing asynchronous and event-based programs using observable sequences for the Java VM"(一个在 Java VM 上使用可观测的序列来组成异步的.基于事件的程序的库).这就是 RxJava ,概括得非常精准. 之前注意到coding APP启动页很是酷炫,今天我们使用RxJava和属性动画模仿实现其效果.

  • Android中用RxJava和ViewPager实现轮播图

    前言 很多人要实现轮播图都会想到使用ViewPager + Handler来完成轮播图的效果.但是在RxJava快速发展的情况下,已经可以使用RxJava来代替Handler完成这样任务了. 下面我们就来介绍如何实现RxJava+ViewPager的轮播图. 效果图如下 ViewPager的操作 说到ViwePager应该大家都不陌生,它可以结合普通的View也可以结合Fragment一起使用.在此我也就不对它的使用方法进行过多的介绍了.直接开始介绍轮播的方法. 常见的轮播操作 private

  • Java扩展库RxJava的基本结构与适用场景小结

    基本结构 我们先来看一段最基本的代码,分析这段代码在RxJava中是如何实现的. Observable.OnSubscribe<String> onSubscriber1 = new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { subscriber.onNext("1"); subscrib

  • Java的RxJava库操作符的用法及实例讲解

    操作符就是为了解决对Observable对象的变换的问题,操作符用于在Observable和最终的Subscriber之间修改Observable发出的事件.RxJava提供了很多很有用的操作符. 比如map操作符,就是用来把把一个事件转换为另一个事件的. Observable.just("Hello, world!") .map(new Func1<String, String>() { @Override public String call(String s) { r

  • RxJava入门之介绍与基本运用

    前言 因为这个RxJava内容不算少,而且应用场景非常广,所以这个关于RxJava的文章我们会陆续更新,今天就来先来个入门RxJava吧 初识RxJava 什么是Rx 很多教程在讲解RxJava的时候,上来就介绍了什么是RxJava.这里我先说一下什么是Rx,Rx就是ReactiveX,官方定义是: Rx是一个函数库,让开发者可以利用可观察序列和LINQ风格查询操作符来编写异步和基于事件的程序 看到这个定义我只能呵呵,稍微通俗点说是这样的: Rx是微软.NET的一个响应式扩展.Rx借助可观测的序

  • RxJava入门指南及其在Android开发中的使用示例

    RxJava的GitHub主页,部署部分就没什么好说的了~ https://github.com/ReactiveX/RxJava 基础 RxJava最核心的两个东西是Observables(被观察者,事件源)和Subscribers(观察者).Observables发出一系列事件,Subscribers处理这些事件.这里的事件可以是任何你感兴趣的东西(触摸事件,web接口调用返回的数据...) 一个Observable可以发出零个或者多个事件,知道结束或者出错.每发出一个事件,就会调用它的Su

随机推荐