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());
                      }
                  }
              });
      
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章