新浦京81707con > 软件下载 > zip操作符在Android中的实际使用场景,网络请求时

原标题:zip操作符在Android中的实际使用场景,网络请求时

浏览次数:55 时间:2020-03-17

等级总括:

完整的流水生产线被减弱到了壹个函数中,rxjava本人的retrywhen和subject机制,已经替大家达成了这样几点:1、自动重试的注册和反注册,subject被回调完直接失效,再度呼吁要重复挂号。2、高并发request,维护队列,通过mTokenObservable的回调自动消除了这一个标题3、retry次数的有限支撑,由于每趟request的retry都以重新创建的里边类,所以变量的维护变的大致。4、重试的逻辑被retry操作符自动完毕了,只要重写retry的重临值就能够垄断重试的战略。

2.利用Intercept(参考那篇小说,然则Okhttpclien3.0删减了ErrorHandler)onErrorResumeNext操作符完成app与服务器间token机制
http://blog.csdn.net/johnny901114/article/details/51533586
在intercept方法中获得重回的json字符串,然后判别token是或不是失效,假使失效,那么重新登陆,不过那时候须求注意的是因为急需连续往下传递哀告,登陆接口的呼吁必得是一道的!(ps:后来相恋的人想了另三个措施,在intercept中抛出特别,这儿就须求用到第三种办法了)

PAJEROxJava体系文章目录导读:

TokenLoader:Token的获得进度
public class TokenLoader { public static final String TAG = TokenLoader.class.getSimpleName(); private AtomicBoolean mRefreshing = new AtomicBoolean; private PublishSubject<String> mPublishSubject; private Observable<String> mTokenObservable; private TokenLoader() { final TokenRequest request = new TokenRequest(CarOperateApplication.getInstance; mTokenObservable = Observable .defer(new Callable<ObservableSource<TokenRequest>>() { @Override public ObservableSource<TokenRequest> call() throws Exception { return Observable.just; } }) .flatMap(new Function<TokenRequest, ObservableSource<MapiHttpResponse<Boolean>>>() { @Override public ObservableSource<MapiHttpResponse<Boolean>> apply(RefreshKeyRequest refreshKeyRequest) throws Exception { //Token请求接口 return ApiHelper.sendDynamicKey(refreshKeyRequest,new MapiTypeReference<MapiHttpResponse<Boolean>>; } }) .retryWhen(new Function<Observable<Throwable>, ObservableSource<TokenRequest>>() { private int retryCount = 0; @Override public ObservableSource<TokenRequest> apply(Observable<Throwable> throwableObservable) throws Exception { return throwableObservable.flatMap(new Function<Throwable, ObservableSource<TokenRequest>>() { @Override public ObservableSource<RefreshKeyRequest> apply(Throwable throwable) throws Exception { retryCount  ; if (retryCount == 3){ //失败次数达到阈值,更改请求策略 request.setFlag; return Observable.just; } else if (retryCount > 3){ //失败次数超过阈值,抛出失败,放弃请求 mRefreshing.set; return Observable.error(throwable); } else { //再次请求token return Observable.just; } } }); } }) // .delay(6000, TimeUnit.MILLISECONDS) //模拟token请求延迟 .map(new Function<MapiHttpResponse<Boolean>,String>() { @Override public String apply(MapiHttpResponse<Boolean> response) throws Exception { //成功,保存token缓存 if (response.getContent().booleanValue() == true){ setCacheToken(response.getToken; } else if (response.getContent().booleanValue() == false){ setCacheToken(UcarK.getSign; } //请求完成标识 mRefreshing.set; return getCacheToken; } public static TokenLoader getInstance() { return Holder.INSTANCE; } private static class Holder { private static final TokenLoader INSTANCE = new TokenLoader(); } public String getCacheToken() { return Store.sToken; } public void setCacheToken(String key){ Store.sToken = key; } /** * * @return */ public Observable<String> getNetTokenLocked() { if (mRefreshing.compareAndSet(false, true)) { Log.d(TAG, "没有请求,发起一次新的Token请求"); startTokenRequest(); } else { Log.d(TAG, "已经有请求,直接返回等待"); } return mPublishSubject; } private void startTokenRequest() { mPublishSubject = PublishSubject.create(); mTokenObservable.subscribe(mPublishSubject); }}

抑或读注释,除了注释以外,几点说明:1、mRefreshing的效率是在token央求进程中,不再允许新的token央求,变量采纳原子类,而非boolean;那样在八线程处境下,原子类的主意是线程安全的。compareAndSet(boolean expect, boolean update)那几个艺术三个职能1)相比expect和mRefresh是不是一致2)将mRefreshing置为update

2、startTokenRequest()方法开启token央浼,注意Observable在subscribe时才正式开班

3、这里运用了PublishSubject较为重大,在rxjava中Subject既是observable,又是observer,在TokenLoader中,mPublishSubject是mTokenObservable的观察者,token必要的会由mPublishSubject响应,同不平时间mPublishSubject也充当Observable重返给TokenLoader的调用者作为retryWhen的重临值再次来到。(所以这里PublishSubject的泛型与send()方法中Observable的泛型应该是相符的)

4、对于mRefreshing是true的气象,间接回到mPublishSubject,那样各种堵塞的央求retryWhen都会等待mPublishSubject的再次来到值,回调通知的逐一与投入窒碍的依次是队列关系(先央求的接口,先回调),满意我们的供给。

末尾:感到什么,是大放光明依旧越陷越深,不管那么都不曾关系,你必要的是询问还存在另一种管理异步义务的艺术。在你下一遍相遇近似让您脑瓜疼的主题素材时,你能够把那篇小说拿起来再看看,大概你的高烧会好一点了。。。

再来说第二条涉及的非常抛出十分的章程

二、zip操作符实际案例

急需描述:

在很多app种都会有图片上传的功能,比如商品的评价,
客户端允许用户拍照上传(可能多张),
把图片上传到又拍云(现在很多中小型公司都是用又拍云作为图片服务器),
然后获取图片的url,再把图片的信息(图片url,图片大小)发送给服务器。

器重逻辑:

1,先把装有的图纸上传来又拍云(举个例子3张图片)

2,获取图片的url路线,图片大小等

3,最后把多少总体付给给服务器

        //需要上传的图片
        Picture[] ps = xxx;
        Observable.zip(
                Observable.from(ps),
                getUpYunAddress(ps.length),//获取上传的url
                new Func2<Picture, UpYunAddress, Picture>() {
                    @Override
                    public Picture call(Picture picture, UpYunAddress upYunAddress) {
                        //如果该图片已经上传则不应该上传
                        if (TextUtils.isEmpty(picture.getSource())) {
                            try {
                                //使用又拍云提供的工具类,上传图片
                                String path = UpYunUtil.uploadImage(upYunAddress, picture.getLocalUrl());
                                //获取最终的url
                                String finalUrl = upYunAddress.getPrefix()   path;
                                picture.setSource(finalUrl);
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                        return picture;
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                //上传成功后获取图片大小
                .flatMap(new Func1<Picture, Observable<Picture>>() {
                    @Override
                    public Observable<Picture> call(Picture picture) {
                        if (TextUtils.isEmpty(picture.getHeight()) || TextUtils.isEmpty(picture.getWidth())) {
                            BitmapFactory.Options options;
                            if (!TextUtils.isEmpty(picture.getLocalUrl())) {
                                options = ImageUtil.getBitmapOptions(picture.getLocalUrl());
                                picture.setLocalUrl(null);
                            } else {
                                options = ImageUtil.getBitmapOptions(picture.getSource());
                            }
                            picture.setWidth(String.valueOf(options.outWidth));
                            picture.setHeight(String.valueOf(options.outHeight));
                        }
                        return Observable.just(picture);
                    }
                });
                //最后处理最终的数据。

代码的注释特别详尽,作者就不再赘述了!


对此复杂的职业,使用陆风X8xJava来解决,认为贯虱穿杨般,再也不用种种复杂的嵌套了。 :D)


正文的例证放在github上https://github.com/chiclaim/android-sample/tree/master/rxjava

杰出复杂异步场景 -- Token的停放校验

时常遭受这种需要,接口的诉求信赖token音信。三个伸手需求先恳求token(token假诺存在缓存则利用缓存),注重这一个token能力展开正规互联网央求。那么些token有一定的时间效益性,在时效性内能够运用缓存,过期后需求重新须求token并再一次发起一次倡议。这么些流程能够总结如下图:

图片 1token前置诉求.png

光看这个供给,是否以为已经够你喝一壶了,别忙,还有个别潜在的逻辑那么些图未有彰显出来:1 高并发互连网需要时,要是token正在倡议,需求对央求梗塞(token须求进程中,不再选拔新的token伏乞)2 不通的还要,要把那一个伏乞记录下来,token央求成功后,再‘依次’发送这个堵塞的伸手。3 token失效情形下,网络乞请限定重试次数。4 token诉求我,重试战术需单独布署。

1、互连网诉求前,对token是或不是有缓存剖断,若无先要求token,并把这么些供给窒碍且缓存2、token诉求进程中,如若有新的token诉求步入,出席拥塞队列3、token央浼后,文告梗塞的类别,依次张开围堵的伸手4、对三种次数节制,分别做逻辑剖断

上述就是传统达成方式,就不贴代码了,那样达成成以下特点:1、要任何时候爱慕三个梗塞队列 (注意其丰裕和清空的机遇)2、token供给甘休后,有叁个回调机制通告窒碍队列,(那一个回调必要注册和反注册)3、两处的次数节制,次数维护的变量,不佳维护(平日动态秘钥为了有扶植使用会做成单例,单例内的变量相仿static,维护较复杂)4、须求重试的逻辑倒霉达成,

我们得以看出此间提到到无数静态变量的护卫,广播等异步回调的管理,这种状态一多,编制程序者会变得很衰颓。並且token的异步须要和真正的互连网异步央浼杂糅在联合具名,增大了难点的复杂。

一部分代码互联网乞求部分与前一篇博客《基于哈弗xJava Retrofit的互连网框架》相关。

2017.1.16更新:使用BlockingObservable卡住操作符能够制止了这种现象:
例如说登陆接口重回很慢(慢的越过了retryCount*retryDelay米尔is),那么会一向重试登入接口和follow数据接口,直到超越重试次数,假使此刻依然未有收获到数量,才会抛出极度,具体的看代码。

一、奥德赛xJava create操作符的用法和源码深入分析
二、大切诺基xJava map操作符用法安详严整
三、揽胜xJava flatMap操作符用法安详严整
四、KoleosxJava concatMap操作符用法安详严整
五、RAV4xJava onErrorResumeNext操作符达成app与劳务器间token机制
六、路虎极光xJava retryWhen操作符完毕错误重试机制
七、纳瓦拉xJava 使用debounce操作符优化app搜索功用
八、牧马人xJava concat操作管理超级多据源
九、OdysseyxJava zip操作符在Android中的实际应用情况
十、LANDxJava switchIfEmpty操作符达成Android检查本地缓存逻辑决断
十二、ENCORExJava defer操作符实今世码援助链式调用
十五、combineLatest操作符的高端应用
十七、途达xJava引致Fragment Activity内部存储器泄漏难题
十三、interval、takeWhile操作符实现获取验证码功效

先看看完整的乞请进度
public static <R> Observable send(final MapiHttpRequest request, final MapiTypeReference<R> t){ return Observable.defer(new Callable<ObservableSource<String>>() { @Override public ObservableSource<String> call() throws Exception { //传入token缓存 return Observable.just(Store.sToken); } }).flatMap(new Function<String, ObservableSource<R>>() { @Override public ObservableSource<R> apply(String key) throws Exception { if(TextUtils.isEmpty && !request.skipCheckKeyValid{ //token没有缓存,需要请求Token return Observable.<R>error(new KeyNotValidThrowable; } else { //Token存在缓存,直接请求 return sendRequestInternal(request,t); } } }) //进入失败重试流程 .retryWhen(new Function<Observable<? extends Throwable>, ObservableSource<String>>() { private int retryCount = 0; @Override public ObservableSource<String> apply(Observable<? extends Throwable> throwableObservable) throws Exception { return throwableObservable.flatMap(new Function<Throwable, ObservableSource<String>>() { @Override public ObservableSource<String> apply(Throwable throwable) throws Exception { if (throwable instanceof KeyNotValidThrowable){ //同一Request,有过一次KeyNotValidThrowable,则不再重试 if (retryCount > 0){ return Observable.error(throwable); } else { //token缓存不在,进入TokenLoader请求token retryCount  ; return TokenLoader.getInstance().getNetTokenLocked(); } } else if (throwable instanceof ApiException){ //token过期的情况,重新获取token,并重试 ApiException apiException = (ApiException)throwable; if (apiException.getCode() == MapiResultCode.SECRETKEY_EXPIRED.value{ if (retryCount > 0){ return Observable.error(throwable); } else { //token缓存失效,进入TokenLoader请求token retryCount  ; return DynamicKeyLoader.getInstance().getNetTokenLocked(); } } } //其他类型错误,直接抛出,不再重试 return Observable.error(throwable); } }); } });}

或是你首先次看也挺晕,别怕,你顺着注释捋捋逻辑,是或不是深感代码的贯彻近似画了三个时序图。除了注释以外,几点表明:1、defer操作符的意义是在retry时,会另行创造新的Observable,不然会接受上次的Observable,不会再一次赢得Store.sToken2、retryWhen操作符,与sendRequestInternal内部统一布署的retryWhen并不矛盾,约等于三次retry3、retryWhen中要是抛出error ,则不再重试;4、重试诉求,通过再次回到getNetTokenLocked这些subject完毕。

 Observable.just(null).flatMap(new Func1<Object, Observable<FollowLive>>() {
            @Override
            public Observable<FollowLive> call(Object o) {
                return ApiClient.getInstance().getLiveApi().getFollow(cookie);
            }
        })

一、zip操作符概述

官方文书档案描述:

Returns an Observable that emits the results of a specified combiner function applied to combinations of two items emitted,
in sequence, by two other Observables.

流程图:
[图片上传战败...(image-3d036b-1516513403287卡塔尔(قطر‎]

由此可见的话zip操作符就是联合多少个数据流,
接下来发送(Emit卡塔尔(قطر‎最后归总的数目。

本文由新浦京81707con发布于软件下载,转载请注明出处:zip操作符在Android中的实际使用场景,网络请求时

关键词: 新浦京81707con 日记本 Android... 场景 Token

上一篇:仿直播送礼物,自定义优雅的BezierSeekBar

下一篇:没有了