Retrofit学习(二)

之前的Retrofit学习(一)了解了一下Retrofit的最基本使用,不过目前最流行的Retrofit使用方式是Retrofit + RxJava + Gson, 如果要使用RxJava, 需要在创建Retrofit时配置RxJava对应的CallAdapter:

    OkHttpclient client = new OkHttpClient.Builder().build();
    Retrofit retrofit = new Retrofit.Builder()
        .client(client)
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
        .baseUrl("http://localhost:4567/")
        .build();

下面就主要分析一下RxJava2CallAdapterFactory是如何工作的

RxJava2CallAdapterFactory

    public static RxJava2CallAdapterFactory create() {
        return new RxJava2CallAdapterFactory(null, false);
    }
    
    public static RxJava2CallAdapterFactory createAsync() {
        return new RxJava2CallAdapterFactory(null, true);
    }
    
    public static RxJava2CallAdapterFactory createWithScheduler(Scheduler scheduler) {
        if (scheduler == null) throw new NullPointerException("scheduler == null");
        return new RxJava2CallAdapterFactory(scheduler, false);
    }
    
    private final Scheduler scheduler;
    private final boolean isAsync;
    
    private RxJava2CallAdapterFactory(Scheduler scheduler, boolean isAsync) {
        this.scheduler = scheduler;
        this.isAsync = isAsync;
    }

RxJava2CallAdapterFactory提供了三个create系列方法,一般情况下,最常使用的是第一个没有参数的create方法,即不指定SchedulerisAsync = false, isAsync指明是调用Call.execute还是Call.enqueue

RxJava2CallAdapterFactory.get


    public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
        Class<?> rawType = getRawType(returnType);

        if (rawType == Completable.class) {
            return new RxJava2CallAdapter(Void.class, scheduler, isAsync, false, true, false, false,
                    false, true);
        }

        boolean isFlowable = rawType == Flowable.class;
        boolean isSingle = rawType == Single.class;
        boolean isMaybe = rawType == Maybe.class;
        //确保返回值是Observable, Flowable, Single, Maybe
        if (rawType != Observable.class && !isFlowable && !isSingle && !isMaybe) {
            return null;
        }

        boolean isResult = false;
        boolean isBody = false;
        Type responseType;
        //ParameterizedType指泛型类型,如List<T>
        if (!(returnType instanceof ParameterizedType)) {
            String name = isFlowable ? "Flowable"
                    : isSingle ? "Single"
                    : isMaybe ? "Maybe" : "Observable";
            throw new IllegalStateException(...);
        }

        //获取返回值的泛型参数
        Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);
        Class<?> rawObservableType = getRawType(observableType);
        if (rawObservableType == Response.class) {
            //如果泛型参数是Response, 且Response没有泛型参数,抛出异常,Response必须是以泛型形式使用
            if (!(observableType instanceof ParameterizedType)) {
                throw new IllegalStateException(...);
            }
            //获取Response<T>中的T
            responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
        } else if (rawObservableType == Result.class) {
            //如果泛型参数是Result, 且Result没有泛型参数, 抛出异常,Result必须是以泛型形式使用
            if (!(observableType instanceof ParameterizedType)) {
                throw new IllegalStateException(...);
            }
            //获取Result<T>中的T
            responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
            isResult = true;
        } else {
            responseType = observableType;
            isBody = true;
        }

        return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, isFlowable,
                isSingle, isMaybe, false);
    }``

  1. 如果返回值类型是Completable, 直接返回一个RxJava2CallAdapter指定其中的isBody = true, isCompletable = true
  2. 确保方法的返回值Observable, Flowable, Single, Maybe, 否则返回null, 如果是null, 则根据之前的分析,如果CallAdapter.Factory.get()返回null, 在Retrofit.nextCallAdapter中会抛出异常(Retrofit默认有一个ExecutorCallAdapterFactory, 但如果方法返回值不是Call类型,其get()方法会直接返回null)
  3. 如果返回值不是泛型,抛出异常
  4. 获取返回值中的泛型参数的类型,假设返回值类型Observable<Bean>, 这里获取到的泛型参数类型就是Bean
  5. 如果泛型参数的类型是retrofit2.Responseretrofit2.Result,确保ResponseResult也是以泛型的形式声明的,即返回值类型是Observable<Response<T>>Observable<Result<T>>Retrofit + RxJava2最常见的的用法是Observable<Bean> getName(...), 一般都会直接使用自定义的Bean类, 所以一般情况下, isBody = true
  6. 返回RxJava2CallAdapter

RxJava2CallAdapter.adapt


    public Object adapt(Call<R> call) {
        //call是OkHttpCall, 将R转换为Response<R>
        Observable<Response<R>> responseObservable = isAsync
                ? new CallEnqueueObservable<>(call)
                : new CallExecuteObservable<>(call);

        Observable<?> observable;
        if (isResult) {
            observable = new ResultObservable<>(responseObservable);
        } else if (isBody) {
            //将Response<T>转换为T
            observable = new BodyObservable<>(responseObservable);
        } else {
            observable = responseObservable;
        }

        if (scheduler != null) {
            observable = observable.subscribeOn(scheduler);
        }

        if (isFlowable) {
            return observable.toFlowable(BackpressureStrategy.LATEST);
        }
        if (isSingle) {
            return observable.singleOrError();
        }
        if (isMaybe) {
            return observable.singleElement();
        }
        if (isCompletable) {
            return observable.ignoreElements();
        }
        return observable;
    }
  1. 首先生成一个Obsersavle<Response<R>>, 这里会根据isAsync是否为tru,来确定是生成CallEnqueueObservable还是CallExecuteObservable,这两者的区别在于前者最终实际是调用OkHttpCall.enqueue方法,后者实际调用了OkHttpCall.execute方法, 前者异步执行,后者同步执行
  2. Retrofit + RxJava2最常见的的用法是Observable<Bean> getName(...), 一般都会直接使用自定义的Bean类,
  3. 根据之前的分析可以知道,一般情况下,由于开发者都直接使用自己的Bean, 所以isBody = true, 会创建一个BodyObservable
  4. 之后会根据方法返回值是否是Flowable, Single, Maybe, Completable其中一种来做出具体的转换

BodyObservable

final class BodyObservable<T> extends Observable<T> {
    private final Observable<Response<T>> upstream;

    BodyObservable(Observable<Response<T>> upstream) {
        this.upstream = upstream;
    }

    @Override
    protected void subscribeActual(Observer<? super T> observer) {
        //upstream是CallExecuteObservable或CallEnqueueObservable, BodyObserver是一个代理
        //作用就是把Response<T>转换为T
        upstream.subscribe(new BodyObserver<T>(observer));
    }

    private static class BodyObserver<R> implements Observer<Response<R>> {
        private final Observer<? super R> observer;
        private boolean terminated;

        BodyObserver(Observer<? super R> observer) {
            this.observer = observer;
        }

        @Override
        public void onSubscribe(Disposable disposable) {
            observer.onSubscribe(disposable);
        }

        @Override
        public void onNext(Response<R> response) {
            if (response.isSuccessful()) {
                observer.onNext(response.body());
            } else {
                ...
            }            }
        }

        @Override
        public void onComplete() {
            if (!terminated) {
                observer.onComplete();
            }
        }

        @Override
        public void onError(Throwable throwable) {
            if (!terminated) {
                observer.onError(throwable);
            } else {
                ...
            }
        }
    }
}

这里upstreamCallExecutorObservableCallEnqueueObservable,一般情况下,这里会是CallExecutorObservable在subscribeActual中可以看到,在传入的observer外又包装了一个BodyObserver, 传入的observer就是开发者传入的自定义Observer

CallExecutorObservable

final class CallExecuteObservable<T> extends Observable<Response<T>> {
    private final Call<T> originalCall;

    CallExecuteObservable(Call<T> originalCall) {
        this.originalCall = originalCall;
    }

    @Override
    protected void subscribeActual(Observer<? super Response<T>> observer) {
        //originalCall是OkHttpCall
        Call<T> call = originalCall.clone();
        observer.onSubscribe(new CallDisposable(call));

        boolean terminated = false;
        try {
            //call.execute会调用OkHttpCall.execute(), 从而得到okhttp3.Response
            //再从okhttp3.Response中得到okhttp3.ResponseBody, 然后调用    Converter.convert转换结果,最后将接过封装为retrofit.Response
            Response<T> response = call.execute();
            if (!call.isCanceled()) {
                //BodyObserver.onNext -> 自定义Onserver.onNext
                observer.onNext(response);
            }
            if (!call.isCanceled()) {
                terminated = true;
                observer.onComplete();
            }
        } catch (Throwable t) {
            ...
        }
    }

    private static final class CallDisposable implements Disposable {
        private final Call<?> call;

        CallDisposable(Call<?> call) {
            this.call = call;
        }

        @Override
        public void dispose() {
            call.cancel();
        }

        @Override
        public boolean isDisposed() {
            return call.isCanceled();
        }
    }
}

originalCallOkHttpCall, 可以看到在subscribeActual中会调用call.execute即调用OkHttpCall.execute来从而得到okhttp3.Response, 再从okhttp3.Response中得到okhttp3.ResponseBody, 然后调用 Converter.convert转换结果,最后将结果封装为retrofit.Response,

subscribeActual的参数observerBodyObserver, 而从之前的分析中可以看到BodyObserver的各方法会再调用开发人员自定义的Observer的响应方法

这里看似比较抽象的一系列操作,是为了获得一个统一的结果, 一般开发人员在定义请求方法时,都会使用Observable<Bean>这种方式,即直接将Observable<T>中的T设为自定义Bean, 但不同场景下肯定会定义不同的类型Bean, Retrofit不可能预先知道开发人员会定义那些Bean, 为了得到一个统一的结果,先将Bean转换为Reponse<T>,这样无论T是哪种类型,都可以得到一个统一的结果,之后再通过Response.body()将Response转换为自定义Bean

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,100评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,568评论 25 707
  • 概述 上一篇已经记载了关于Retrofit使用的相关知识,这一片主要记录下Retrofit实现的相关原理。简要来说...
    seph_von阅读 482评论 0 0
  • Retrofit学习(一)官网原文翻译http://www.jianshu.com/writer#/noteboo...
    冉冉升起的小太阳阅读 297评论 0 0
  • 雾夕急匆匆的跑到纪念的药房,翻箱倒柜的找了整整一天一夜 ,把整个药房都翻了个底朝天都没没能把仙芝草给找出来。 第二...
    梦多多阅读 320评论 0 1