Rxjava使用,没有理论只有实战

  1. 线程切换->subscribeOnobserveOn

    Observable.just(1,2,3,4)
        .doOnNext {
            println("parade订阅observeOn${Thread.currentThread().name}")
            //当subscribeOn在Schedulers.io()时  打印parade订阅observeOnRxCachedThreadScheduler-1
            //当subscribeOn在AndroidSchedulers.mainThread()时  打印parade订阅observeOnmain
        }
        .observeOn(AndroidSchedulers.mainThread())
        .doOnNext{
            println("parade第一次observeOn${Thread.currentThread().name}")//parade第一次observeOnmain
            println("parade value is $it")
        }
        .observeOn(Schedulers.io())
        .map {
            it * 3
            println("parade第二次observeOn${Thread.currentThread().name}")//parade第二次observeOnRxCachedThreadScheduler-2
        }
        .observeOn(AndroidSchedulers.mainThread())
        .doOnNext{
            println("parade第三次observeOn${Thread.currentThread().name}")//parade第三次observeOnmain
        }
        .subscribeOn(AndroidSchedulers.mainThread())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe()
    

    由实例代码可以看出observeOn指定的是它之后的操作所在的线程,而subscribeOn指定产生订阅时的线程,另外这样做的好处是给用户的的体验是用户感觉不到多次请求,也就是说如果要显示加载Dialog,那么从请求登录开始显示dialog到请求用户信息结束dialog消失,所以用户才感觉不到。从订阅到整个请求链结束是一个完整的过程

  2. 操作符flatMap->用来把一个Observable转成另外一个Observable

    1. 示例场景->登录:先调用登录接口,登录成功后保存返回的token并接着调用获取个人信息的接口

    2. 代码实例

      ApiService.getUserApi().loginWithMobile(etLoginAccount.getText().toString()
              , EncryptUtils.encryptMD5ToString(etLoginPwd.getText().toString().trim()).toLowerCase()
              , etLoginCode.getText().toString().trim())
              .observeOn(AndroidSchedulers.mainThread())//这里不可少,请求登录用的是subscribeOn的io线程,登录请求后切到主线程保存token或者刷新登录验证码
              .doOnNext(new Consumer<StringModel>() {
                  @Override
                  public void accept(StringModel stringModel) throws Exception {
                      //登录成功
                      app.getDataCenter().setToken(stringModel.getValue());
                      SPUtils.getInstance().put(SP_NAME_KEY, etLoginAccount.getText().toString().trim());
                      SPUtils.getInstance().put(SP_PWD_KEY,etLoginPwd.getText().toString().toString());
                  }
              })
              .doOnError(new Consumer<Throwable>() {
                  @Override
                  public void accept(Throwable throwable) throws Exception {
                      //登录失败,刷新二维码,线程由上面的observeOn指定,是在主线程,因此可以更新UI
                      etLoginCode.setText("");
                      requestPhotoCode();
                  }
              })
              .observeOn(Schedulers.io())//处理完登录接口后,再去调用请求个人信息接口
              .flatMap(new Function<StringModel, ObservableSource<UserModel>>() {
                  @Override
                  public ObservableSource<UserModel> apply(StringModel stringModel) throws Exception {
                      return ApiService.getUserApi().getUserInfo();
                  }
              })
              .subscribeOn(Schedulers.io())
              .observeOn(AndroidSchedulers.mainThread())
              .subscribe(new BaseObserver<UserModel>(mContext, true) {
                          @Override
                          public void onNext(UserModel userModel) {
                              //缓存用户信息
                              app.getDataCenter().setUserModel(userModel);
                              jumpActivity(MainActivity.class);
                          }
                      });
      

      另外一个场景->上传图片,需要支持用户同时上传多张,但是接口只允许每次上传一张

      Observable.fromIterable(parts)
              .flatMap(new Function<MultipartBody.Part, ObservableSource<Object>>() {
                  @Override
                  public ObservableSource<Object> apply(MultipartBody.Part part) throws Exception {
                      return ApiService.getProjectApi().uploadFile(part,Constant.orderAttach);
                  }
              })
              .subscribeOn(Schedulers.io())
              .observeOn(AndroidSchedulers.mainThread())
              .subscribe(new BaseObserver<Object>(mContext,true,"上传中") {
                  @Override
                  public void onNext(Object o) {
                      TLog.e("上传成功");
                      String attachUrl = (String) ((LinkedTreeMap) o).get("value");
                      if (selectAdapter.getData().size() == Constant.orderAttachMaxSelect) {
                          selectAdapter.getData().get(Constant.orderAttachMaxSelect - 1).setItemType(ImageVo.IMAGE);
                          selectAdapter.getData().get(Constant.orderAttachMaxSelect - 1).setImageUrl(attachUrl);
                          selectAdapter.notifyItemChanged(Constant.orderAttachMaxSelect - 1);
                      } else {
                          selectAdapter.addData(selectAdapter.getData().size() - 1, new ImageVo(ImageVo.IMAGE, attachUrl));
                      }
                      if (selectAdapter.getData().size() == Constant.orderAttachSpan + 1) {
                          new Handler().post(new Runnable() {
                              @Override
                              public void run() {
                                  nestScrollView.fullScroll(NestedScrollView.FOCUS_DOWN);//滚动到底部
                              }
                          });
                      }
                      attacheString = getAttachesString(selectAdapter.getData());
                      previewImages = getPreviewList(attachUrl);
                  }
              });
      
  3. 操作符merge->用来合并两个没有关联的请求

    1. 示例场景,有些界面展示的数据需要通过两个不相关的接口获得,因此可以同时进行请求,如果不使用类似merge的合并操作符,那么给用户的直观是进行了两次请求(如果要显示dialog,那两个请求的dialog是独立的),使用merge就可以使用一个dialog

    2. 示例代码

      Observable<Feedback> feedbackInfoByAdviceId = NetWork.getOaService().getFeedbackInfoByAdviceId(themeId);
      Observable<AdviceTheme> adviceThemeById = NetWork.getOaService().getAdviceThemeById(themeId);
      Subscription subscription = Observable.merge(feedbackInfoByAdviceId,adviceThemeById)
              .subscribeOn(Schedulers.io())
              .observeOn(AndroidSchedulers.mainThread())
              .subscribe(new BaseSubscriber<Object>(FeedBackDetailActivity.this){
                  @Override
                  public void onNext(Object o) {
                      //因为两个Observable返回的数据类型不一致,所以这里要用Object接收并进行类型判断
                      if (o instanceof  Feedback){
                          tvFeedContent.setText(((Feedback)o).getContent());
                      }else if (o instanceof AdviceTheme){
                          AdviceTheme a = (AdviceTheme) o;
                          tvThemeTitle.setText(a.getTitle());
                          CommonUtils.parseHtml(tvThemeContent,a.getContent());
                      }
                  }
              });
      
  4. 观察者模式

    1. 身边的一直在使用的观察者模式->控件的点击事件监听

      //控件button是被观察者,匿名内部类OnClickListener是观察者,setOnclickListener是订阅,回调方法onClick是事件,只有订阅了才会响应监听事件
      button.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
              
          }
      });
      
    2. Rxjava的观察者模式

      //在Rxjava的默认规则中,事件的发起和消费都是在同一个线程,也就是可以同步观察,虽然Rxjava就是为了异步观察(哈哈),再详细一点就是在哪个线程调用subscribe就在哪个线程产生事件,在哪个线程产生事件就在哪个线程消费事件
      //Rxjava的事件分为3种 onNext,onError和onComplete
      //只有订阅了,被观察这才会发送事件(发起网络请求)->通常是一个事件序列,若干个onNext,一个onComplete或一个onError
      Observable.just(1)//1.创建被观察者
              .subscribeOn(Schedulers.io())//指定在io线程产生事件
              .observeOn(AndroidSchedulers.mainThread())//在主线程消费事件
              .subscribe(new Observer<Integer>() {//2.subscribe订阅 3.new Observer观察者
                  @Override
                  public void onSubscribe(@NonNull Disposable d) {
                  }
                  @Override
                  public void onNext(@NonNull Integer integer) {
                      //4.事件,相当于(onClick)
                  }
                  @Override
                  public void onError(@NonNull Throwable e) {
                      //4.事件
                  }
                  @Override
                  public void onComplete() {
                      //4.事件
      
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值