android常用框架源码分析

Rxjava

优点:基于事件流的链式调用,逻辑简洁,使用简单

引入

简单看一下Rxjava 一般使用方式

//观察者
Observable.create(new ObservableOnSubscribe(){

            @Override
            public void subscribe(ObservableEmitter emitter) throws Exception {
				//ObservableEmitter emitter 被观察者
                //数据改变者
            }
        }).
    //订阅者
    subscribe(new Observer() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(Object o) {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        });

说明:

Observable创建需要ObservableOnSubscribe接口 

当调用subscribe时 根据observer 创建ObservableEmitter 发射器

    emitter反射器回调 observer中的方法

map和flatmap

map:返回的是结果集,只能单一转换,每传递一个事件执行一次onNext方法

flatmap:返回Observable,可以多对多 一对多,一对一转换 一般利用from/just进行分发

操作符

1 interval:创建一个按固定时间间隔发射整数序列的Observable

Observable.interval(3, TimeUnit.SECONDS).subscribe(new Consumer<Long>() {
            @Override
            public void accept(Long aLong) throws Exception {
                Log.e("zgt", String.valueOf(aLong));
            }
        });

每隔3秒调用一次

2 range 发射指定范围的整数 可以拿了替换for循环

 Observable.range(0, 10).subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) throws Exception {
                Log.e("zgt", String.valueOf(integer));
            }
        });

3 repeat 创建一个N次重复发射特定数据的Observable

Observable.range(0,3).repeat(2).subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) throws Exception {
                System.out.println(integer);
            }
        });

变换操作符

1 map 将Obserable 转换为一个新的Obserable

Observable.just("abc").map(r->r.substring(0,1)).subscribe((t)->{
            System.out.println(t);
        });

2 flatMap,cast flatMap 将Observable 发射的数据集合 变换为新的Observable集合,可以多对多 一对多,一对一转换 一般利用from/just进行分发。cast 强制将Obserable发射的数据转换为指定的类型


Observable.fromIterable(Arrays.asList("abc","zgt","hello")).flatMap(new Function<String, ObservableSource<?>>() {
            @Override
            public ObservableSource<?> apply(String s) throws Exception {
                return Observable.fromArray("a","b",s);
            }
        }).subscribe(t->{
            System.out.println(t);
        });


3 concatMap 和flatMap 一样 解决了flatMap交叉问题

如果想要最后输出的事件顺序和源数据的顺序一致只要换成concatMap就可以了

Observable.fromIterable(Arrays.asList("abc","zgt","hello")).concatMap(new Function<String, ObservableSource<?>>() {
            @Override
            public ObservableSource<?> apply(String s) throws Exception {
                return Observable.fromArray("a","b",s);
            }
        }).subscribe(t->{
            System.out.println(t);
        });

4 flatMapIterable将数据包装成Iterable

Observable.just(1,2,3,4).flatMapIterable(new Function<Integer, Iterable<?>>() {
            @Override
            public Iterable<?> apply(Integer integer) throws Exception {
                return Arrays.asList(integer+1);
            }
        }).subscribe(t->{
            System.out.println(t);
        });

5 buffer 将Observable变换为一个新的Observable 这个新的Observable每次发射一组列表

Observable.just(1,2,3,4,5,6).buffer(4).subscribe(new Consumer<List<Integer>>() {
            @Override
            public void accept(List<Integer> integers) throws Exception {
                System.out.println(integers);
            }
        });

6 groupBy 分组 将源Observable变换成新的Observable 它们中的每一个新的Observable都发射一组指定的数据

Observable<GroupedObservable<String, String>> groupedObservableObservable = Observable.just( "bxxx","abc", "abd", "azzz", "bvvv").groupBy(t -> t.substring(0, 1));
        Observable.concat(groupedObservableObservable).subscribe(new Consumer<String>() {
            @Override
            public void accept(String s) throws Exception {
                System.out.println(s);
            }
        });

过滤操作符

1 filter 对Observable产生的数据结果进行过滤只有满足条件的结果才交给订阅者

Observable.just(1,2,3,4).filter(t->t%2==0).subscribe(t->{
            System.out.println(t);
        });

2 elementAt 用来返回指定位置的数据

Observable.just(1,2,3,4).elementAt(2).subscribe(t->{
            System.out.println(t);
        });

3 distinct 去重

Observable.just(1,2,1,2,3,1,1,1,1,1).distinct().subscribe(t->{
            System.out.println(t);
        });

4 skip, take skip 将源Observable数据过滤掉前n项 take 只取前N项

 Observable.just(1,2,3,4,5,6,7).skip(3).subscribe(t->{
            System.out.println(t);
        });
        Observable.just(1,2,3,4,5,6,7).take(3).subscribe(t->{
            System.out.println(t);
        });

5 ignoreElements 忽略Observable产生的结果

Observable.just(1,2,3,4,5,6,7).ignoreElements().subscribe();

6 throttleFirst 定期发射这个时间段里Observable的第一个数据

Observable.create(new ObservableOnSubscribe<Integer>() {

            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                for (int i = 0; i <10 ; i++) {

                    emitter.onNext(i);
                    Thread.sleep(100);
                }
            }
        }).throttleFirst(200,TimeUnit.MILLISECONDS).subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) throws Exception {
                System.out.println(integer);
            }
        });

组合操作符

1 startWith 在Observable发射的数据前面加上一些数据

 Observable.just(3,4,5).startWith(1).startWithArray(1,2,6).subscribe(t->{
            System.out.println(t);
        });

2 merge 将多个Observable合并到一个Observable发射数据交错

Observable<Integer> obs1 = Observable.just(1, 2, 3).subscribeOn(Schedulers.io());
        Observable<Integer> obs2 = Observable.just(4,5,6);
        Observable.merge(obs1,obs2).subscribe(t->{
            System.out.println(t);
        });

3 concat 将多个Observable 发射的数据进行合并发射 concat严格按照顺序发射数据,前一个observable没有完成不会发射下一个observable

 Observable.concat(obs1,obs2).subscribe(t->{
            System.out.println(t);
        });

4 zip 合并两个或者多个Observable发射出数据项 根据指定的函数变换它们并发射一个新值

Observable<Integer> o1 = Observable.just(1, 2, 3);
        Observable<String> o2 = Observable.just("a","b","c","d");

        Observable.zip(o1, o2, (t1,t2)->String.valueOf(t1)+String.valueOf(t2))
        .subscribe(t->{
            System.out.println(t);
        });

5 combineLastest 类似zip 区别 o1 最后元素 与 o2没有元素合并

Observable<Integer> o1 = Observable.just(1, 2, 3,4);
Observable<String> o2 = Observable.just("a","b","c");
Observable.combineLatest(o1, o2, (t1,t2)->String.valueOf(t1)+String.valueOf(t2))
.subscribe(t->{
System.out.println(t);
});

辅助操作符

1 delay 在发射数据之前都暂停一段时间

 Observable.just(1,2,3,4,5).delay(2,TimeUnit.SECONDS).subscribe(t->{
            System.out.println(t);
        });

2 Do 为原始Observable的生命周期事件注册一个回调

1, doOnEach: 当Observable 每发射一项数据就会调用它一次 包括onNext onError onCompleted

2,doOnNExt:只有执行onNext的时候会调用

3,doOnSubscribe:当观察者订阅Observable时调用

4,doOnUnsubscribe:当观察者取消订阅时调用

5,doOnCompleted:当Observable正常终止调用onCompleted 会调用

6,doOnError:当Observable异常终止调用onError时会被调用

7,doOnTerminate:当Observable终止(无论正常还是异常)之前会被调用

8,finallyDo:当Observable终止(无论正常还是异常)之后会被调用

    ```java

Observable.just(1,2,3,4).doOnNext(t->{
System.out.println(t);
}).subscribe(new Observer() {
@Override
public void onSubscribe(Disposable disposable) {
System.out.println(“onSubscribe”);
}

        @Override
        public void onNext(Integer integer) {
            System.out.println("onNext");
        }

        @Override
        public void onError(Throwable throwable) {
            System.out.println("onError");
        }

        @Override
        public void onComplete() {
            System.out.println("onComplete");
        }
    });
    ```

3 subscribeOn,observeOn

subscribeOn:指定Observable在哪个线程上运行

observeOn:指定Observable所运行的线程,也就是发射出的数据在哪个线程上使用
Observable<Integer> observable = Observable.create(new ObservableOnSubscribe(){
            @Override
            public void subscribe(ObservableEmitter observableEmitter) throws Exception {
                System.out.println(Thread.currentThread().getName());
                observableEmitter.onNext(1);
                observableEmitter.onNext(2);
                observableEmitter.onComplete();
            }
        });
        observable.subscribeOn(Schedulers.newThread()).observeOn(Schedulers.single()).subscribe(t->{
            System.out.println(Thread.currentThread().getName());
            System.out.println(t);
        });

4 timeout :原始Observable过了指定时间没有发射任何数据 timeout会以一个onError通知这个Observable终止或者继续执行一个备用的Observable

Observable<Integer> obs3 = Observable.create(new ObservableOnSubscribe(){
            @Override
            public void subscribe(ObservableEmitter observableEmitter) throws Exception {
                Thread.sleep(2000);
                observableEmitter.onNext(2);
            }
        });
        obs3.timeout(1,TimeUnit.SECONDS,Observable.just(3)).subscribe(new Observer<Integer>() {
            @Override
            public void onSubscribe(Disposable disposable) {
                //System.out.println("onSubscribe");
            }

            @Override
            public void onNext(Integer integer) {
                System.out.println("onNext");
            }

            @Override
            public void onError(Throwable throwable) {
                System.out.println("onError");
            }

            @Override
            public void onComplete() {
                // System.out.println("onComplete");
            }
        });

错误处理操作符

1 catch :拦截原始Observable的onError通知,将它替换为其它数据项或数据序列

 1,onErrorReturn:当Observable遇到错误时返回原有Observable行为备用的Observable,会忽略原有的Observable的onError回调

 2,onErrorResumeNext:

 3,onErrorResumeNext:

 4,onExceptionResumeNext:
Observable o4 = Observable.create(new ObservableOnSubscribe(){

            @Override
            public void subscribe(ObservableEmitter emitter) throws Exception {
                //emitter.onNext(1);
                emitter.onError(new Throwable("error"));

            }
        });

//        Observable o5 = o4.onErrorReturn(new Function() {
//            @Override
//            public Object apply(Object o) throws Exception {
//                System.out.println(">>>>"+ o.toString());
//                return "zgt";
//            }
//        });

        Observable o5 = o4.onErrorResumeNext(new ObservableSource(){

            @Override
            public void subscribe(Observer observer) {
                observer.onNext(3);
            }
        });

        o5.subscribe(new Observer() {
            @Override
            public void onSubscribe(Disposable disposable) {
                System.out.println("onSubscribe");
            }

            @Override
            public void onNext(Object o) {
                System.out.println("onNext");
            }

            @Override
            public void onError(Throwable throwable) {
                System.out.println("onError");
            }

            @Override
            public void onComplete() {
                System.out.println("onComplete");
            }
        });

2 retry :将原始Observable 发射了错误 retry 会重新发射数据重复n次 到onNext 这个可能造成数据重复

 Observable o5 = o4.retry(3);

条件操作符和布尔操作符

布尔操作符

1 all 根据一个函数对源Observable 发射的所有数据进行判断

Observable.just(1,2,3,4).all(new Predicate<Integer>() {
            @Override
            public boolean test(Integer integer) throws Exception {
                System.out.println(integer);
                return integer<3;
            }
        }).subscribe(t->{
            System.out.println(t);
        });

2,contains ,isEmpty

contains:判断Obaservable 发射的数据中是否包含某个数据如果包含返回 true

isEmpty:判断Observable是否发射过数据
 Observable.just(1,2,3).contains(2).subscribe(t->{
            System.out.println(t);
        });

        Observable.just(1,2,3).isEmpty().subscribe(t->{
            System.out.println(t);
        });

条件操作符

条件操作符有 amb , defaultIfEmpty,skipUntil,skipWhile,takeUntil,takeWhile 等

1 amb 对于给定的两个Observable 它只发射首先发射的Observable

Observable.ambArray(Observable.just(1,2),Observable.just(3,4,5)).subscribe(t->{
            System.out.println(t);
        });

2 defaultIfEmpty 发射原始Observable 如果原始的Observable没有数据 就发射一个默认数据

Observable.create(new ObservableOnSubscribe(){

            @Override
            public void subscribe(ObservableEmitter emitter) throws Exception {
                emitter.onComplete();
            }
        } ).defaultIfEmpty(3).subscribe(t->{
            System.out.println(t);
        });

转换操作符

1,toList :发射多项数据合并成一个List 然后调用一次onNext方法传递整个列表

Observable.just(1,2,4).toList().subscribe(t->{
            System.out.println(t);
        });

2,toSortedList 类似toList 它会对产生的列表排序

Observable.just(3,1,4,8).toSortedList().subscribe(t->{
            System.out.println(t);
        });

3,toMap 搜集原始Observable数据发射到一个map中(默认HashMap)

Observable.just(1,2,3).toMap(new Function(){

            @Override
            public Object apply(Object o) throws Exception {
                return "key_"+o;
            }
        }).subscribe(t->{
            System.out.println(t);
        });

RxJava 线程控制

1,内置的调度器Scheduler

1,Schedulers.trampoline( ) 直接在当前线程运行

Observable.just(1,2,3).subscribeOn(Schedulers.trampoline()).subscribe(t->{
           System.out.println(Thread.currentThread().getName());
       });

2,Schedulers.newThread() 总是启用新的线程

Observable.just(1,2,3).subscribeOn(Schedulers.newThread()).subscribe(t->{
            System.out.println(Thread.currentThread().getName());
        });

3,Schedulers.io() I/O 操作 内部实现是用一个无数量上限的线程池,可以重用空闲的线程池,因此io比newThread更有效率

Observable.just(1,2,3).subscribeOn(Schedulers.io()).subscribe(t->{
    System.out.println(Thread.currentThread().getName());
});

4,Schedulers.computation() 计算所使用的线程池 例如图形的计算 内部使用了固定的线程池,大小为cpu核数

不要把io操作放到computation中否则io的操作等待浪费cpu。他是buffer debounce delay interval sample 和 skip 操作符的默认调度器

Observable.just(1,2,3).subscribeOn(Schedulers.computation()).subscribe(t->{
    System.out.println(Thread.currentThread().getName());
});

5,AndroidSchedulers.mainThread(): android 中切换到主线程

2,控制线程

使用 subscribeOn和observeOn 操作符来控制线程

subscribeOn:用于该操作符之前的 Observable

observeOn:用于该操作符之后的 Observable

OKhttp

基本用法

1,最简单的get请求
Request.Builder builder = new Request.Builder();
builder.url("http://www.baidu.com");
builder.method("GET",null);
Request request=builder.build();
OkHttpClient client = new OkHttpClient();
Call call = client.newCall(request);
call.enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {

    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        String str = response.body().string();
        System.out.println(str);
    }
});
2,异步post 请求
RequestBody formBody = new FormBody.Builder()
        .add("ip","59.108.54.37")
        .build();
Request request = new Request.Builder()
        .url("http://ip.taobao.com/service/getIpInfo.php")
        .post(formBody)
        .build();
OkHttpClient client = new OkHttpClient();
Call call = client.newCall(request);
call.enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
    }
    @Override
    public void onResponse(Call call, Response response) throws IOException {
        String str = response.body().string();
        System.out.println(str);
    }
});
3,异步上传文件
MediaType markdown = MediaType.parse("text/x-markdown; charset=utf-8");
File file = new File("xxxx.txt");
Request request = new Request.Builder()
        .url("http://xxxxx")
        .post(RequestBody.create(markdown,file))
        .build();
OkHttpClient client = new OkHttpClient();
Call call = client.newCall(request);
call.enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
    }
    @Override
    public void onResponse(Call call, Response response) throws IOException {
        String str = response.body().string();
        System.out.println(str);
    }
});
4,异步下载文件
Request request = new Request.Builder()
    .url("https://ss0.baidu.com/6ONWsjip0QIZ8tyhnq/it/u=423512187,2285661156&fm=173&app=25&f=JPEG?w=640&h=320&s=9FA0E9044ECA972C0CECA1D30100C0B1")
    .build();
OkHttpClient client = new OkHttpClient();
Call call = client.newCall(request);
call.enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        InputStream in = response.body().byteStream();
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        byte []bytes = new byte[1024];
        int len =0;
        while ((len = in.read(bytes))>0){
            out.write(bytes, 0, len);
        }
        in.close();
        out.flush();
        byte[] bytes1 = out.toByteArray(); //图片数据
        out.close();
    }
});
6 异步上传Multipart 文件
MediaType mediaPng = MediaType.parse("image/png");
OkHttpClient client = new OkHttpClient();
RequestBody requestBody = new MultipartBody.Builder()
        .setType(mediaPng)
        .addFormDataPart("title","xxx" )
        .addFormDataPart("image", "xxx.png",RequestBody.create(mediaPng, new File("/sdcard/xxx.png")))
        .build();
Request request = new Request.Builder()
        .header("Authorization", "Client-ID")
        .url("https://api.imgur.com/3/image")
        .post(requestBody)
        .build();
client.newCall(request).enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        System.out.println(response.body().string());
    }
});
6 设置超时时间和缓存
File sdcache = context.getExternalCacheDir();
int cacheSize = 10 * 1024 *1024;
OkHttpClient client = new OkHttpClient.Builder()
        .connectTimeout(15, TimeUnit.SECONDS)
        .writeTimeout(20, TimeUnit.SECONDS)
        .readTimeout(20,TimeUnit.SECONDS )
        .cache(new Cache(sdcache, cacheSize))
        .build();
7,取消请求
Request request = new Request.Builder()
        .url("http://www.baidu.com")
        .cacheControl(CacheControl.FORCE_NETWORK)
        .build();
OkHttpClient client = new OkHttpClient();

Call call = client.newCall(request);
//取消请求
call.cancel();
call.enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        if (null != response.cacheResponse()){
            System.out.println(response.cacheResponse().toString());
        }else {
            System.out.println(response.networkResponse().toString());
        }
    }
});

源码解析

异步请求

request->Client->RealCall->Dispatcher->Async->ThreadPool->InterceptorChain->Response

同步请求

request->Client->RealCall->Dispatcher->Sync->InterceptorChain->Response

1,OkHttp请求网络流程

call=client.newCall(request);

call.enqueue(new Callback())

newCall 返回给我们的是RealCall 然后调用RealCall的enqueue方法

@Override public void enqueue(Callback responseCallback) {
  synchronized (this) {
    if (executed) throw new IllegalStateException("Already Executed");
    executed = true;
  }
  captureCallStackTrace();
  eventListener.callStart(this);
  client.dispatcher().enqueue(new AsyncCall(responseCallback));
}

可以看到最终是有dispatcher来完成的

2,Dispatcher 任务调度
//最大并非请求
private int maxRequests = 64;
//每个主机最大请求数
private int maxRequestsPerHost = 5;
private @Nullable Runnable idleCallback;

/** 消费者线程池 */
private @Nullable ExecutorService executorService;

/** 将要运行的请求队列 */
private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();

/** 正在运行的异步请求队列 */
private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();

/** 正在运行的同步请求队列 */
private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();

构造方法

public Dispatcher(ExecutorService executorService) {
  this.executorService = executorService;
}

public Dispatcher() {
}

//默认创建的线程池
public synchronized ExecutorService executorService() {
  if (executorService == null) {
    executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
        new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
  }
  return executorService;
}

默认的线程池比较适合执行大量的耗时,任务比较少的情况

也可以自定义线程池

synchronized void enqueue(AsyncCall call) {
  //当前运行的异步请求队列中数量小于64 并且正在运行的请求主机小于5时 把请求加载到runningAsynCalls进行缓存等待  
  if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
    runningAsyncCalls.add(call);
    executorService().execute(call);
  } else {
    readyAsyncCalls.add(call);
  }
}

参数AsyncCall 是RealCall内部类 实现了Runable接口 实现execute方法

RealCall 实现的execute方法

@Override public Response execute() throws IOException {
  synchronized (this) {
    if (executed) throw new IllegalStateException("Already Executed");
    executed = true;
  }
  captureCallStackTrace();
  eventListener.callStart(this);
  try {
    client.dispatcher().executed(this);
    Response result = getResponseWithInterceptorChain(); //请求网络中的数据
    if (result == null) throw new IOException("Canceled");
    return result;
  } catch (IOException e) {
    eventListener.callFailed(this, e);
    throw e;
  } finally {
      //无论如何都要调用 dispatcher的finished 方法  通知下一个 让下个来运行
    client.dispatcher().finished(this);
  }
}

Dispatcher 的finished方法中调用promoteCalls方法

private void promoteCalls() {
  if (runningAsyncCalls.size() >= maxRequests) return; // Already running max capacity.
  if (readyAsyncCalls.isEmpty()) return; // No ready calls to promote.

  for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
    AsyncCall call = i.next();

    if (runningCallsForHost(call) < maxRequestsPerHost) {
      i.remove();
      runningAsyncCalls.add(call);
      executorService().execute(call);
    }

    if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.
  }
}

从readyAsyncCalls 队列中取出 来执行

3,Iinterceptor 拦截器

使用责任链模式:例如请假,A 向领导B请假 B 说我去找我的领导C 领导 C 找领导D

D 告诉C同意 C告诉B 好,同意 B告诉A 同意你了 A拿到了结果数据 同意你了 可以对数据加工

Response result = getResponseWithInterceptorChain(); //请求网络中的数据

源码

Response getResponseWithInterceptorChain() throws IOException {
  // Build a full stack of interceptors.
  List<Interceptor> interceptors = new ArrayList<>();
  interceptors.addAll(client.interceptors());//添加自定义的拦截器
  interceptors.add(retryAndFollowUpInterceptor);
  interceptors.add(new BridgeInterceptor(client.cookieJar()));
  interceptors.add(new CacheInterceptor(client.internalCache()));
  interceptors.add(new ConnectInterceptor(client));
  if (!forWebSocket) {
    interceptors.addAll(client.networkInterceptors());
  }
  interceptors.add(new CallServerInterceptor(forWebSocket));

  Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
      originalRequest, this, eventListener, client.connectTimeoutMillis(),
      client.readTimeoutMillis(), client.writeTimeoutMillis());

  return chain.proceed(originalRequest);
}
public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
    RealConnection connection) throws IOException {
  if (index >= interceptors.size()) throw new AssertionError();

  calls++;

  // If we already have a stream, confirm that the incoming request will use it.
  if (this.httpCodec != null && !this.connection.supportsUrl(request.url())) {
    throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
        + " must retain the same host and port");
  }

  // If we already have a stream, confirm that this is the only call to chain.proceed().
  if (this.httpCodec != null && calls > 1) {
    throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
        + " must call proceed() exactly once");
  }

  // Call the next interceptor in the chain.
  RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
      connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
      writeTimeout);
  Interceptor interceptor = interceptors.get(index);
  Response response = interceptor.intercept(next);

  // Confirm that the next interceptor made its required call to chain.proceed().
  if (httpCodec != null && index + 1 < interceptors.size() && next.calls != 1) {
    throw new IllegalStateException("network interceptor " + interceptor
        + " must call proceed() exactly once");
  }

  // Confirm that the intercepted response isn't null.
  if (response == null) {
    throw new NullPointerException("interceptor " + interceptor + " returned null");
  }

  if (response.body() == null) {
    throw new IllegalStateException(
        "interceptor " + interceptor + " returned a response with no body");
  }

  return response;
}

拦截器:是一种能够监控,重写,重试调用的机制。通常情况下用来添加,移除,转换请求 和响应头部信息。例如将域名替换为ip地址,在请求头上添加host属性等等

4, 缓存策略

CacheInterceptor 缓存拦截器

//缓存文件夹
File cacheFile = new File(getExternalCacheDir().toString(),"cache");
//缓存大小为10M
int cacheSize = 10 * 1024 * 1024;
//创建缓存对象
Cache cache = new Cache(cacheFile,cacheSize);

OkHttpClient client = new OkHttpClient.Builder()
        .cache(cache)
        .build();

缓存根据响应头 Cache-Control:max-age=60 来决定缓存多长时间,如果响应头不存在Cache-Control:max-age=60 可以自定义拦截器修改响应头

class CacheInterceptor implements Interceptor{

        @Override
        public Response intercept(Chain chain) throws IOException {

            Response originResponse = chain.proceed(chain.request());

            //设置缓存时间为60秒,并移除了pragma消息头,移除它的原因是因为pragma也是控制缓存的一个消息头属性
            return originResponse.newBuilder().removeHeader("pragma")
                    .header("Cache-Control","max-age=60").build();
        }
    }

//缓存文件夹
File cacheFile = new File(getExternalCacheDir().toString(),"cache");
//缓存大小为10M
int cacheSize = 10 * 1024 * 1024;
//创建缓存对象
final Cache cache = new Cache(cacheFile,cacheSize);

OkHttpClient client = new OkHttpClient.Builder()
    .addNetworkInterceptor(new CacheInterceptor())
    .cache(cache)
    .build();
okhttp官方文档建议缓存方法
//缓存文件夹
File cacheFile = new File(getExternalCacheDir().toString(),"cache");
//缓存大小为10M
int cacheSize = 10 * 1024 * 1024;
//创建缓存对象
final Cache cache = new Cache(cacheFile,cacheSize);

OkHttpClient client = new OkHttpClient.Builder()
    .cache(cache)
    .build();
//设置缓存时间为60秒
CacheControl cacheControl = new CacheControl.Builder()
    .maxAge(60, TimeUnit.SECONDS)
    .build();
Request request = new Request.Builder()
    .url("http://blog.youkuaiyun.com/briblue")
    .cacheControl(cacheControl)
    .build();

Cache 类

Cache(File directory, long maxSize, FileSystem fileSystem) {
  this.cache = DiskLruCache.create(fileSystem, directory, VERSION, ENTRY_COUNT, maxSize);
}

在Cache类的构造方法中创建了DiskLruCache类型的cache 实例,这里的FileSystem.SYSTEM是FileSystem(文件系统接口)的实现,其内部是基于Okio的sink/source对缓存文件进行流操作。在DiskLruCache.Entry内部维护了两个数组,保存每个url请求对应文件的引用。然后通过DiskLruCache.Editor操作DiskLruCache.Entry中的数组,并为Cache.Entry提供Sink/source,对文件流进行操作。这点会在后续分析Cache的put和get中证实。

5,失败重连

RetryAndFollowUpInterceptor 失败重试拦截器

用于创建StreamAllocation 能重试21次或者取消退出

@Override public Response intercept(Chain chain) throws IOException {
  Request request = chain.request();
  RealInterceptorChain realChain = (RealInterceptorChain) chain;
  Call call = realChain.call();
  EventListener eventListener = realChain.eventListener();

  StreamAllocation streamAllocation = new StreamAllocation(client.connectionPool(),
      createAddress(request.url()), call, eventListener, callStackTrace);
  this.streamAllocation = streamAllocation;

  int followUpCount = 0;
  Response priorResponse = null;
  while (true) {
    if (canceled) {
      streamAllocation.release();
      throw new IOException("Canceled");
    }

    Response response;
    boolean releaseConnection = true;
    try {
      response = realChain.proceed(request, streamAllocation, null, null);
      releaseConnection = false;
    } catch (RouteException e) {
      // The attempt to connect via a route failed. The request will not have been sent.
      if (!recover(e.getLastConnectException(), streamAllocation, false, request)) {
        throw e.getLastConnectException();
      }
      releaseConnection = false;
      continue;
    } catch (IOException e) {
      // An attempt to communicate with a server failed. The request may have been sent.
      boolean requestSendStarted = !(e instanceof ConnectionShutdownException);
      if (!recover(e, streamAllocation, requestSendStarted, request)) throw e;
      releaseConnection = false;
      continue;
    } finally {
      // We're throwing an unchecked exception. Release any resources.
      if (releaseConnection) {
        streamAllocation.streamFailed(null);
        streamAllocation.release();
      }
    }

    // Attach the prior response if it exists. Such responses never have a body.
    if (priorResponse != null) {
      response = response.newBuilder()
          .priorResponse(priorResponse.newBuilder()
                  .body(null)
                  .build())
          .build();
    }

    Request followUp = followUpRequest(response, streamAllocation.route());

    if (followUp == null) {
      if (!forWebSocket) {
        streamAllocation.release();
      }
      return response;
    }

    closeQuietly(response.body());

    if (++followUpCount > MAX_FOLLOW_UPS) {
      streamAllocation.release();
      throw new ProtocolException("Too many follow-up requests: " + followUpCount);
    }

    if (followUp.body() instanceof UnrepeatableRequestBody) {
      streamAllocation.release();
      throw new HttpRetryException("Cannot retry streamed HTTP body", response.code());
    }

    if (!sameConnection(response, followUp.url())) {
      streamAllocation.release();
      streamAllocation = new StreamAllocation(client.connectionPool(),
          createAddress(followUp.url()), call, eventListener, callStackTrace);
      this.streamAllocation = streamAllocation;
    } else if (streamAllocation.codec() != null) {
      throw new IllegalStateException("Closing the body of " + response
          + " didn't close its backing stream. Bad interceptor?");
    }

    request = followUp;
    priorResponse = response;
  }
}

OkHttp复用连接池

Http中有一种叫keep alive connections 的机制;okhttp支持5个并发socket连接 默认keepalive时间为5分钟

ConnectionPool

 private static final Executor executor = new ThreadPoolExecutor(0 /* corePoolSize */,
      Integer.MAX_VALUE /* maximumPoolSize */, 60L /* keepAliveTime */, TimeUnit.SECONDS,
      new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp ConnectionPool", true));

//最大空闲socket最大连接数
private final int maxIdleConnections;
//socket的keepAlive时间
private final long keepAliveDurationNs;

//双向队列 经常在缓存中使用  RealConnection socket物理连接
private final Deque<RealConnection> connections = new ArrayDeque<>();
//用来记录连接失败的路线名单,当连接失败的时候就把失败的线路加进去
final RouteDatabase routeDatabase = new RouteDatabase();


public ConnectionPool() {
    //空闲socket5个 keepAlive时间5分钟
    this(5, 5, TimeUnit.MINUTES);
}

executor 线程池采用了没有容量的SynchronousQueue

缓存操作
//添加之前先清理空闲的线程
void put(RealConnection connection) {
  assert (Thread.holdsLock(this));
  if (!cleanupRunning) {
    cleanupRunning = true;
    executor.execute(cleanupRunnable);
  }
  connections.add(connection);
}

//遍历connections列表当某个连接的次数小于限制的大小,并且request的地址和缓存列表中此连接完匹配时则直接复用缓存列表中connection作为request的连接
@Nullable RealConnection get(Address address, StreamAllocation streamAllocation, Route route) {
    assert (Thread.holdsLock(this));
    for (RealConnection connection : connections) {
      if (connection.isEligible(address, route)) {
        streamAllocation.acquire(connection, true);
        return connection;
      }
    }
    return null;
  }
自动回收连接
private final Runnable cleanupRunnable = new Runnable() {
  @Override public void run() {
    while (true) {
        //不断调用cleanup方法清理 并返回下次需要清理的间隔时间,然后调用wait方法进行等待以释放锁与时间片,当等待时间到了后,再次进行清理,并返回下次要清理的时间
      long waitNanos = cleanup(System.nanoTime());
      if (waitNanos == -1) return;
      if (waitNanos > 0) {
        long waitMillis = waitNanos / 1000000L;
        waitNanos -= (waitMillis * 1000000L);
        synchronized (ConnectionPool.this) {
          try {
            ConnectionPool.this.wait(waitMillis, (int) waitNanos);
          } catch (InterruptedException ignored) {
          }
        }
      }
    }
  }
};


//根据连接中的引用计数来计算空闲连接数和活跃连接数,然后标记出空闲的连接,如果空闲的连接超过5分钟,或者连接个数超过5个则从Deque中移除此连接,接下来根据空闲连接或者活跃连接来返回下次需要清理的时间数:如果空闲连接大于0,则返回此连接即将到期的时间,如果都是活跃连接并且大于0则返回默认的keepAlive时间5分钟。
//如果没有任何连接返回-1
//通过pruneAndGetAllocationCount 来判断连接是否空闲,如果返回值大于0 则是空闲连接,或者就是活跃连接
long cleanup(long now) {
    int inUseConnectionCount = 0;
    int idleConnectionCount = 0;
    RealConnection longestIdleConnection = null;
    long longestIdleDurationNs = Long.MIN_VALUE;

    // Find either a connection to evict, or the time that the next eviction is due.
    synchronized (this) {
      for (Iterator<RealConnection> i = connections.iterator(); i.hasNext(); ) {
        RealConnection connection = i.next();

        // If the connection is in use, keep searching.
        if (pruneAndGetAllocationCount(connection, now) > 0) {
          inUseConnectionCount++;
          continue;
        }

        idleConnectionCount++;

        // If the connection is ready to be evicted, we're done.
        long idleDurationNs = now - connection.idleAtNanos;
        if (idleDurationNs > longestIdleDurationNs) {
          longestIdleDurationNs = idleDurationNs;
          longestIdleConnection = connection;
        }
      }

      if (longestIdleDurationNs >= this.keepAliveDurationNs
          || idleConnectionCount > this.maxIdleConnections) {
        // We've found a connection to evict. Remove it from the list, then close it below (outside
        // of the synchronized block).
        connections.remove(longestIdleConnection);
      } else if (idleConnectionCount > 0) {
        // A connection will be ready to evict soon.
        return keepAliveDurationNs - longestIdleDurationNs;
      } else if (inUseConnectionCount > 0) {
        // All connections are in use. It'll be at least the keep alive duration 'til we run again.
        return keepAliveDurationNs;
      } else {
        // No connections, idle or in use.
        cleanupRunning = false;
        return -1;
      }
    }

    closeQuietly(longestIdleConnection.socket());

    // Cleanup again immediately.
    return 0;
  }


//首先遍历传进来的RealConnection的StreamAllocation列表
//如果StreamAllocation被使用,则接着遍历下一个StreamAllocation 如果StreamAlloction未被使用则从列表中删除,如果列表为空则说明此连接没有引用了返回0,否则就返回非0表示此连接是活跃的
private int pruneAndGetAllocationCount(RealConnection connection, long now) {
  List<Reference<StreamAllocation>> references = connection.allocations;
  for (int i = 0; i < references.size(); ) {
    Reference<StreamAllocation> reference = references.get(i);

    if (reference.get() != null) {
      i++;
      continue;
    }

    // We've discovered a leaked allocation. This is an application bug.
    StreamAllocation.StreamAllocationReference streamAllocRef =
        (StreamAllocation.StreamAllocationReference) reference;
    String message = "A connection to " + connection.route().address().url()
        + " was leaked. Did you forget to close a response body?";
    Platform.get().logCloseableLeak(message, streamAllocRef.callStackTrace);

    references.remove(i);
    connection.noNewStreams = true;

    // If this was the last allocation, the connection is eligible for immediate eviction.
    if (references.isEmpty()) {
      connection.idleAtNanos = now - keepAliveDurationNs;
      return 0;
    }
  }

  return references.size();
}
引用计数

StreamAllocation

在okhttp中使用了引用计数方式跟踪socket流的调用计数对象是StreamAllocation

它反复执行acquire,release操作这个两个操作在改变RealConnnection中的List<Reference> 大小

public void acquire(RealConnection connection, boolean reportedAcquired) {
  assert (Thread.holdsLock(connectionPool));
  if (this.connection != null) throw new IllegalStateException();

  this.connection = connection;
  this.reportedAcquired = reportedAcquired;
  connection.allocations.add(new StreamAllocationReference(this, callStackTrace));
}

/** Remove this allocation from the connection's list of allocations. */
private void release(RealConnection connection) {
  for (int i = 0, size = connection.allocations.size(); i < size; i++) {
    Reference<StreamAllocation> reference = connection.allocations.get(i);
    if (reference.get() == this) {
      connection.allocations.remove(i);
      return;
    }
  }
  throw new IllegalStateException();
}

retrofit2

Retrofit基本用法

1,支持解析类型

Scalars,Jackson,Moshi,Protobuf,Wire,SimpleXML,Gson

2,注解分类

http请求方法注解:GET,POST,PUT,DELETE,HEAD,PATCH,OPTIONS

标记类注解3种:FormUrlEncoded,Multipart,Streaming

参数注解10种:Header,Headers,Body,Path,Field,FieldMap,Part,PartMap,Query,QueryMap

3,GET请求访问网络
public interface IpService{
    @GET("getIpInfo.php?ip=xxxx")
    Call<IpModel> getIpMsg();
    
    //动态地址@Path
    @GET("{path}/getIpInfo.php?ip=xxxxx")
    Call<IpModel> getIpMsg(@Path("path")String path);
    
    //动态指定查询条件@Query
     @GET("getIpInfo.php")
     Call<IpModel> getIpMsg(@Query("ip")String ip);
    
    //动态指定查询条件数组
    @GET("getIpInfo.php")
    Call<IpModel> getIpMsg(@QueryMap Map<String,String> options);
}

String BaseUrl = "http://ip.taobao.com/service/";
Retrofit retofit=new Retrofit.Builder()
    .baseUrl(BaseUrl)
    .addConverterFactory(GsonConverterFactory.create())
    .build();
IpService ipService = retrofit.create(IpService.class)
Call<IpModel> call = ipService.getIpMsg();    

4 POST 请求访问网络

@Field:传输类型为键值对

public interface IpServiceForPost{
    
    @FormUrlEncoded //表示这个是一个表单请求
    @POST("getIpInfo.php")
    Call<IpModel> getIpMsg(@Field("ip")String first);
    
    // 将json 字符串发送到服务端
    // @Body 表识 将对象转换为字符串 
    @POST("getIpInfo.php")
    Call<IpModel> getIpMsg(@Body Ip ip);
    
    
    //单个文件上传
    @Multipart //表示允许多个@Part
    @POST("user/photo")
    // MultipartBody.Part 准备上传到图片文件
    //RequestBody 传递简单的键值对
    Call<User> updateUser(@Part MultipartBody.Part photo,@Part("description")RequestBody description);
    
    //多文件上传
    @Multipart
    @POST("user/photo")
    Call<User> updateUser(@PartMap Map<String,RequestBody> photos,@Part("description")RequestBody description);
    
    
    
}

File file = new File(Environment.getExternalStorageDirectory()+"xxx.png");
RequestBody body = RequestBody.create(MediaType.parse("image/png"),file );
MultipartBody.Part part=MultipartBody.Part.createFormData("photos", "xxx.png",body);
IpServiceForPost.updateUser(part,RequestBody.create(null,"xxxxxxx"));


5,消息报头Header

interface SomeService{
    @GET("some/endpoint")
    @Headers("Accept-Encoding:application/json")//添加消息报头
    //如果添加多个消息报头可以使用{}
    // @Headers({"Accept-Encoding:application/json","User-Agent:MoonRetrofit"})
    Call<ResponseBody> getCarType();
    
    //动态方式添加报头
     @GET("some/endpoint")
     Call<ResponseBody> getCarType(@Header("Location") String location);
    
}

源码解析

1,Retrofit 的创建过程

当使用retrofit请求网络时,首先要写请求接口,接着我们创建retrofit

retrofit通过建造者模式构建出来。

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("")
        .addConverterFactory(GsonConverterFactory.create())
        .build();

public Builder() {
      this(Platform.get());
}
//根据不同的平台来提供不同的线程池
private static Platform findPlatform() {
    try {
      Class.forName("android.os.Build");
      if (Build.VERSION.SDK_INT != 0) {
        return new Android();
      }
    } catch (ClassNotFoundException ignored) {
    }
    try {
      Class.forName("java.util.Optional");
      return new Java8();
    } catch (ClassNotFoundException ignored) {
    }
    return new Platform();
  }

//build()方法
public Retrofit build() {
      //baseUrl 必须有
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }
      //我们调用.callFactory(null)  传递进来的
      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
          //将回调传递到UI线程
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // Make a defensive copy of the adapters and add the default Call adapter.
      //用于存储对call进行转化的对象
      List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
    
      //添加默认的 ExecutorCallAdapterFactory 执行器    
      callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

      //用于存储转化数据对象 
      // Make a defensive copy of the converters.
      List<Converter.Factory> converterFactories =
          new ArrayList<>(1 + this.converterFactories.size());

      // Add the built-in converter factory first. This prevents overriding its behavior but also
      // ensures correct behavior when using converters that consume all types.
      converterFactories.add(new BuiltInConverters());
      converterFactories.addAll(this.converterFactories);

      return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
    }
  }

2,Call 的创建过程
 @SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
//返回一个动态代理对象  
public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          private final Platform platform = Platform.get();
		 //proxy 代理对象
         //method 调用方法
         // args 方法参数  
          @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
              throws Throwable {
            // If the method is a method from Object then defer to normal invocation.
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            // loadServiceMethod 调用接口方法 
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.adapt(okHttpCall);
          }
        });
  }

ServiceMethod<?, ?> loadServiceMethod(Method method) {
    //serviceMethodCache 查询传入的方法是否有缓存 如果有就用缓存 如果没有就创建一个并加入serviceMethodCache缓存中
  ServiceMethod<?, ?> result = serviceMethodCache.get(method);
  if (result != null) return result;

  synchronized (serviceMethodCache) {
    result = serviceMethodCache.get(method);
    if (result == null) {
      result = new ServiceMethod.Builder<>(this, method).build();
      serviceMethodCache.put(method, result);
    }
  }
  return result;
}

ServiceMethod 的构建

public ServiceMethod build() {
  //构建接口返回的数据类型  
  callAdapter = createCallAdapter();
   //得到返回数据的真实类型 
  responseType = callAdapter.responseType();
  if (responseType == Response.class || responseType == okhttp3.Response.class) {
    throw methodError("'"
        + Utils.getRawType(responseType).getName()
        + "' is not a valid response body type. Did you mean ResponseBody?");
  }
  //遍历converterFactories列表中存储的Converter.Factories 并返回一个合适的Converter用来转换对象
  responseConverter = createResponseConverter();

  for (Annotation annotation : methodAnnotations) {
     //遍历 parseMethodAnnotation 方法来对请求方式(比如@GET,@POST)和请求地址进行解析
    parseMethodAnnotation(annotation);
  }

  if (httpMethod == null) {
    throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
  }

  if (!hasBody) {
    if (isMultipart) {
      throw methodError(
          "Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
    }
    if (isFormEncoded) {
      throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
          + "request body (e.g., @POST).");
    }
  }

  int parameterCount = parameterAnnotationsArray.length;
  parameterHandlers = new ParameterHandler<?>[parameterCount];
  for (int p = 0; p < parameterCount; p++) {
    Type parameterType = parameterTypes[p];
    if (Utils.hasUnresolvableType(parameterType)) {
      throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
          parameterType);
    }
    //对方法中的参数注解进行解析(比如@Query,@Part)
    Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
    if (parameterAnnotations == null) {
      throw parameterError(p, "No Retrofit annotation found.");
    }
   
    parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
  }

  if (relativeUrl == null && !gotUrl) {
    throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
  }
  if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
    throw methodError("Non-body HTTP method cannot contain @Body.");
  }
  if (isFormEncoded && !gotField) {
    throw methodError("Form-encoded method must contain at least one @Field.");
  }
  if (isMultipart && !gotPart) {
    throw methodError("Multipart method must contain at least one @Part.");
  }

  return new ServiceMethod<>(this);
}

创建CallAdapter

private CallAdapter<T, R> createCallAdapter() {
  Type returnType = method.getGenericReturnType();
  if (Utils.hasUnresolvableType(returnType)) {
    throw methodError(
        "Method return type must not include a type variable or wildcard: %s", returnType);
  }
  if (returnType == void.class) {
    throw methodError("Service methods cannot return void.");
  }
  Annotation[] annotations = method.getAnnotations();
  try {
    //noinspection unchecked
    return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
  } catch (RuntimeException e) { // Wide exception range because factories are user code.
    throw methodError(e, "Unable to create call adapter for %s", returnType);
  }
}

最终调用okhttp请求网络

static final class ExecutorCallbackCall<T> implements Call<T> {
  final Executor callbackExecutor;
    //就是OkhttpCall
  final Call<T> delegate;

  ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
    this.callbackExecutor = callbackExecutor;
    this.delegate = delegate;
  }

  @Override public void enqueue(final Callback<T> callback) {
    checkNotNull(callback, "callback == null");

    delegate.enqueue(new Callback<T>() {
      @Override public void onResponse(Call<T> call, final Response<T> response) {
        callbackExecutor.execute(new Runnable() {
          @Override public void run() {
            if (delegate.isCanceled()) {
              // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
              callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
            } else {
              callback.onResponse(ExecutorCallbackCall.this, response);
            }
          }
        });
      }

      @Override public void onFailure(Call<T> call, final Throwable t) {
        callbackExecutor.execute(new Runnable() {
          @Override public void run() {
            callback.onFailure(ExecutorCallbackCall.this, t);
          }
        });
      }
    });
  }

OkhttpCall 中enqueue

@Override public void enqueue(final Callback<T> callback) {
  checkNotNull(callback, "callback == null");

  okhttp3.Call call;
  Throwable failure;

  synchronized (this) {
    if (executed) throw new IllegalStateException("Already executed.");
    executed = true;

    call = rawCall;
    failure = creationFailure;
    if (call == null && failure == null) {
      try {
        call = rawCall = createRawCall();
      } catch (Throwable t) {
        throwIfFatal(t);
        failure = creationFailure = t;
      }
    }
  }

  if (failure != null) {
    callback.onFailure(this, failure);
    return;
  }

  if (canceled) {
    call.cancel();
  }

  call.enqueue(new okhttp3.Callback() {
    @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
      Response<T> response;
      try {
          //解析请求结果
        response = parseResponse(rawResponse);
      } catch (Throwable e) {
        callFailure(e);
        return;
      }

      try {
        callback.onResponse(OkHttpCall.this, response);
      } catch (Throwable t) {
        t.printStackTrace();
      }
    }

    @Override public void onFailure(okhttp3.Call call, IOException e) {
      callFailure(e);
    }

    private void callFailure(Throwable e) {
      try {
        callback.onFailure(OkHttpCall.this, e);
      } catch (Throwable t) {
        t.printStackTrace();
      }
    }
  });
}

解析请求结果封装成Response对象

Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
  ResponseBody rawBody = rawResponse.body();

  // Remove the body's source (the only stateful object) so we can pass the response along.
  rawResponse = rawResponse.newBuilder()
      .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
      .build();

  int code = rawResponse.code();
  if (code < 200 || code >= 300) {
    try {
      // Buffer the entire body to avoid future I/O.
      ResponseBody bufferedBody = Utils.buffer(rawBody);
      return Response.error(bufferedBody, rawResponse);
    } finally {
      rawBody.close();
    }
  }

  if (code == 204 || code == 205) {
    rawBody.close();
    return Response.success(null, rawResponse);
  }

  ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
  try {
      //根据我们传入的转换工程进行数据转换 比如我们传入 GsonConverFactory
    T body = serviceMethod.toResponse(catchingBody);
    return Response.success(body, rawResponse);
  } catch (RuntimeException e) {
    // If the underlying source threw an exception, propagate that rather than indicating it was
    // a runtime exception.
    catchingBody.throwIfCaught();
    throw e;
  }
}

GsonFactory 转换过程

@Override public T convert(ResponseBody value) throws IOException {
  JsonReader jsonReader = gson.newJsonReader(value.charStream());
  try {
    return adapter.read(jsonReader);
  } finally {
    value.close();
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值