-
线程切换->
subscribeOn
和observeOn
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消失,所以用户才感觉不到。从订阅到整个请求链结束是一个完整的过程 -
操作符flatMap->用来把一个Observable转成另外一个Observable
-
示例场景->登录:先调用登录接口,登录成功后保存返回的token并接着调用获取个人信息的接口
-
代码实例
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); } });
-
-
操作符merge->用来合并两个没有关联的请求
-
示例场景,有些界面展示的数据需要通过两个不相关的接口获得,因此可以同时进行请求,如果不使用类似merge的合并操作符,那么给用户的直观是进行了两次请求(如果要显示dialog,那两个请求的dialog是独立的),使用merge就可以使用一个dialog
-
示例代码
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()); } } });
-
-
观察者模式
-
身边的一直在使用的观察者模式->控件的点击事件监听
//控件button是被观察者,匿名内部类OnClickListener是观察者,setOnclickListener是订阅,回调方法onClick是事件,只有订阅了才会响应监听事件 button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { } });
-
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.事件
-
Rxjava使用,没有理论只有实战
最新推荐文章于 2023-07-02 13:36:15 发布