Retrofit(OkHttp)源码分享

Retrofit(OkHttp)源码分享

一、使用

1.创建接口
public interface CountTryApi {
    @GET("/api/location/country")
    Call<ResponseBody>  getCall(@Query("id") String id);
}
2.发起请求
Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("http://***.com/") // 设置网络请求的公共Url地址
            //.addConverterFactory(GsonConverterFactory.create()) // 设置数据解析器
            //.addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 支持RxJava
            .build();
// 创建网络请求接口的实例
CountTryApi request = retrofit.create(CountTryApi.class);
// 调用方法,对发送请求进行封装
Call<ResponseBody> call = request.getCall("1111");

/发送网络请求(异步)
call.enqueue(new Callback<ResultData>() {
    //请求成功时回调
    @Override
    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
        //处理结果
    }

     //请求失败时候的回调
     @Override
     public void onFailure(Call<ResponseBody> call, Throwable throwable) {
       //提示失败
     }
});

// 发送网络请求(同步)
Response<ResultData> response = call.execute();

二、执行流程

1. 创建Retrofit实例

使用Build设计模式,retrofit中主要参数:

  1. convertFactories:转换结果,可自定义,如addConverterFactory.add(GsonConverterFactory.create())
  2. callFactoty:OkHttpClient(创建连接池connectionPool)
  3. callbackExecutor:切换主线程执行
  4. adapterFactories:请求和回调,可自定义,addCallAdapterFactory(RxJava2CallAdapterFactory.create())

看下我们自定义的addConverterFactory和addCallAdapterFactory执行顺序,执行过程在构造ServiceMethod中

// 先调addCallAdapterFactory,所以我们定义的是加在第0个的
adapter.List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

List<Converter.Factory> converterFactories = new ArrayList<>(1 + this.converterFactories.size());
// 第0个是BuiltInConverters,之后是我们添加的converterFactory
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);

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

callAdapterFactory在使用时

// start = 0,
int start = callAdapterFactories.indexOf(null) + 1;
for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
    CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
    if (adapter != null) {
        return adapter;
    }
}

从第0个开始,找到CallAdapter就返回,所以使用的是我们第一个调用addCallAdapterFactory添加的

converterFactories在使用时:

// start = 0
int start = converterFactories.indexOf(null) + 1;
for (int i = start, count = converterFactories.size(); i < count; i++) {
    Converter<ResponseBody, ?> converter =      converterFactories.get(i).responseBodyConverter(type, annotations, this);
    if (converter != null) {
        return (Converter<ResponseBody, T>) converter;
    }
}

第0个是BuiltInConverters,返回类型是ResponseBody或Void返回对应的converter,否则返回null,返回null就会继续遍历到我们自定义的Converter,所以我们也可以自定义转换某些类型的ConverterFactory,在第一个addConverterFactory添加进来,对于不是这些类型的返回null,再继续遍历后续add的ConverterFactory

2. Retrofit.create返回定义接口代理对象

使用动态代理,返回Proxy.newProxyInstance创建的代理对象,实现invoke方法

动态代理:

public interface TestInterface {
    String getInterface();
}
public class TestProxy {
    public staic void main(String[] args) {
        TestInterface proxy = createProxy();
        System.out.println("\"getInterface\" result: " + proxy.getInterface());
        System.out.println("proxy class: " + proxy.getClass());
        System.out.println("proxy super class: " + proxy.getClass().getSuperclass());
    }

    private TestInterface createProxy() {
        return (TestInterface) Proxy.newProxyInstance(TestInterface.class.getClassLoader(), new Class[]{TestInterface.class}, (InvocationHandler) (proxy, method, args) -> {
            System.out.println("invoke method: " + method.getName());
            return "TestInterface";
        });
    }
}

执行结果

invoke method: getInterface
"getInterface" result: TestInterface
proxy class: class com.sun.proxy.$Proxy4
proxy super class: class java.lang.reflect.Proxy

代理对象实际类型是$Proxy4,代理类是动态构造类信息,生成class文件

生成代理类的源码执行过程

Proxy.newProxyInstance -> Proxy.getProxyClass0 -> WeakCache.get -> Factory.apply -> Factory.get

-> ProxyClassFactory.apply,主要生成class对象的逻辑在ProxyClassFactory.apply,Class对象就是ProxyClassFactory.apply返回的

ProxyClassFactory.apply部分代码

long num = nextUniqueNumber.getAndIncrement();
// proxyPkg包名,默认"com.sun.proxy."
// proxyClassNamePrefix 常量"$Proxy"
// num 自增int
String proxyName = proxyPkg + proxyClassNamePrefix + num;
return generateProxy(proxyName, interfaces, loader, methodsArray,
                     exceptionsArray);

generateProxy是个native方法,我们看Proxy.class中ProxyClassFactory.apply最后这段代码:

long var19 = nextUniqueNumber.getAndIncrement();
String var23 = var16 + "$Proxy" + var19;

// var23 类名 proxyName
// var2 newProxyInstance传的第二个参数 Class[]
// var accessFlags
// 动态生成class文件
byte[] var22 = ProxyGenerator.generateProxyClass(var23, var2, var17);
try {
    // 加载字节码,并返回对应的class对象
    return Proxy.defineClass0(var1, var23, var22, 0, var22.length);
} catch (ClassFormatError var14) {
    throw new IllegalArgumentException(var14.toString());
}

generateProxyClass调用ProxyGenerator.generateClassFile

private byte[] generateClassFile() {
    // 添加Object的方法,使调用这些方法也走invoke
    this.addProxyMethod(hashCodeMethod, Object.class);
    this.addProxyMethod(equalsMethod, Object.class);
    this.addProxyMethod(toStringMethod, Object.class);
    ...
    // 添加自己写的方法到proxyMethods
    for(var3 = 0; var3 < var2; ++var3) {
        Method[] var5 = var4.getMethods();
        for(int var7 = 0; var7 < var6; ++var7) {
            Method var8 = var5[var7];
            this.addProxyMethod(var8, var4);
         }
     }
         // 生成构造函数并添加到method
         this.methods.add(this.generateConstructor());
         // 遍历上述添加的proxyMethods,动态生成method(内部执行到invoke)
         var11 = this.proxyMethods.values().iterator();
         while(var11.hasNext()) {
             var12 = (List)var11.next();
             var15 = var12.iterator();
             while(var15.hasNext()) {
                // ...
                this.methods.add(var16.generateMethod());
              }
          }
          // 添加静态字段的初始化
          this.methods.add(this.generateStaticInitializer());
      ...
      // 把生成的类信息写到文件中
      var14.writeShort(this.cp.getClass(dotToSlash(this.className)));
      ...
      
      }
      return var4;
  }

generateConstructor部分代码

// 生成init方法,构造函数
ProxyGenerator.MethodInfo var1 = new ProxyGenerator.MethodInfo("<init>", "(Ljava/lang/reflect/InvocationHandler;)V", 1);
DataOutputStream var2 = new DataOutputStream(var1.code);
...
return var1;

generateMethod方法部分代码

String var1 = ProxyGenerator.getMethodDescriptor(this.parameterTypes, this.returnType);
ProxyGenerator.MethodInfo var2 = ProxyGenerator.this.new MethodInfo(this.methodName, var1, 17);
DataOutputStream var9 = new DataOutputStream(var2.code);
var9.writeShort(ProxyGenerator.this.cp.getFieldRef("java/lang/reflect/Proxy", "h", "Ljava/lang/reflect/InvocationHandler;"));
// 调用的invoke
var9.writeShort(ProxyGenerator.this.cp.getInterfaceMethodRef("java/lang/reflect/InvocationHandler", "invoke", "(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;"));

generateStaticInitializer部分代码

// 生成clinit,执行静态字段或静态块
ProxyGenerator.MethodInfo var1 = new ProxyGenerator.MethodInfo("<clinit>", "()V", 8);
...
return var1;

生成class对象后,找到InvocationHandler为参数的构造函数,创建实例并返回

Constructor<?> cons = cl.getConstructor(Class[]{ InvocationHandler.class });
return cons.newInstance(new Object[]{h});

生成的$Proxy4类部分代码:

public final class $Proxy4 extends Proxy implements TestInterface {
    public $Proxy4(InvocationHandler var1) throws  {
        super(var1);
    }

    public final String getInterface() throws  {
        try {
            return (String)super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
}
3. 调用代理方法,返回OkHttpCall对象

调用接口方法,执行代理对象实现的invoke方法,解析接口方法的注解,参数,参数注解,以及参数值

ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);
  1. loadServiceMethod,使用Build设计模式,创建ServiceMethod对象

    ServiceMethod

    1.callAdapter :retrofit.callAdapterFactories.get(0).get(retrunType, annotations, retrofit)

    ​ 默认返回ExecutorCallAdapterFactory.CallAdapter对象

    2.responseType :callAdapter.responseType();

    3.responseConverter :retrofit.converterFactories.get(0).responseBodyConverter(type, annotations, this);

    4.parseMethodAnnotation解析注解

    5.parameterHandlers解析参数的注解

    ServiceMethod中包含了请求的信息、执行回调、类型解析,用于后续构造OkHttp.Call

  2. 创建OkHttpCall

    serviceMethod:第1步创建好的ServiceMethod

    args:参数值

  3. 返回Call,默认情况下返回ExecutorCallAdapterFactory.ExecutorCallbackCall

    serviceMethod.adapt(okHttpCall)

    T adapt(Call<R> call) {
        // callAdapter 在我们不自己定义adapterFactory时,是默认的platform.defaultCallAdapterFactory(callbackExecutor),就是ExecutorCallAdapterFactory
        return callAdapter.adapt(call);
    }
    
    return new CallAdapter<Object, Call<?>>() {
        public Type responseType() {
            return responseType;
        }
        public Call<Object> adapt(Call<Object> call) {
            // callbackExecutor 是默认的 MainThreadExecutor,用于切换到主线程
            return new ExecutorCallAdapterFactory.ExecutorCallbackCall(ExecutorCallAdapterFactory.this.callbackExecutor, call);
        }
    };
    
4. 开始执行请求

也就是执行ExecutorCallAdapterFactory.ExecutorCallbackCall.enqueue

public void enqueue(final Callback<T> callback) {
    // delegate就是上述构造的OkHttpCall
    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()) {
                        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) {
    okhttp3.Call call;
    synchronized (this) {
      call = rawCall;
      // ...
      // 创建RealCall,调用ServiceMethod.toCall,传参args(我们调用方法时的参数值)
      // ServiceMethod.callFactory(OkHttpClient).toCall(ServiceMethod中属性组成的Request)
      // 返回RealCall
      call = rawCall = createRawCall();
    }
    // ...
    // 调用异步执行,传入回调接口
    call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
        // 解析为返回类型
        Response<T> response = parseResponse(rawResponse);
        // ...
        callback.onResponse(OkHttpCall.this, response);
      }

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

      private void callFailure(Throwable e) {
        // ...
        callback.onFailure(OkHttpCall.this, e);
      }
    });
  }

RealCall.enqueue

  @Override public void enqueue(Callback responseCallback) {
    // ...
    // AsyncCall也就是一个Runnable
    // diapatch 是管理执行Runnable的类,内部有线程池
    client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }

上面一行执行完后,即调用AsyncCall.execute()方法,里面主要调用了getResponseWithInterceptorChain,代码如下:

Response getResponseWithInterceptorChain() throws IOException {
 
    List<Interceptor> interceptors = new ArrayList<>();  
    // addInterceptor()添加的拦截器
    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) {
        // addNetworkInterceptor()添加的拦截器
        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);
}

okHttpClientBuilder.addInterceptor添加的拦截器,在所有操作发生前和请求并处理完成后操作,如添加base params,打印日志

okHttpClientBuilder.addNetWorkInterceptor添加的拦截器,可以处理可在建立连接发起请求之前和发起请求后做操作,如Stetho,修改默认请求头

5. 拦截器
1. RetryAndFollowUpInterceptor

重试机制

2. BridgeInterceptor

请求头,gzip(可用做流量优化),cookieJar

返回的gzip解压

3. CacheInterceptor

使用缓存,用到OKHttp中的DiskLruCache和Okio(可用做流量优化)

4. ConnectInterceptor

建立连接

5. CallServerInterceptor

真正的发送接收数据的过程

okhttp拦截器

  1. 默认没有缓存,缓存自己定义

    // 自己定义缓存的文件
    File cacheFile = new File(DemoApplication.getContext().getCacheDir(),"demo_repo");
    Cache cache = new Cache(cacheFile, 1024 * 1024 * 50);
    Interceptor cacheInterceptor = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request(); 
            // 没网强制使用缓存
            if (!NetworkUtil.isNetworkAvailable(DemoApplication.getContext())) {                      request = request.newBuilder().cacheControl(CacheControl.FORCE_CACHE).build();
            }
            return chain.proceed(request);
        }};
    builder.cache(cache).addInterceptor(cacheInterceptor);
    
  2. 缓存只对GET请求有效,cache无效,即使设置里only-if-cache

    // 请求完成后
    if (HttpMethod.invalidatesCache(response.request().method())) {
      try {
        remove(response.request());
      } catch (IOException ignored) {
        // The cache cannot be written.
      }
      return null;
    }
    if (!requestMethod.equals("GET")) {
        return null;
    }
    
    // 缓存完成后
    if (cache != null) {
      if (HttpMethod.invalidatesCache(networkRequest.method())) {
        ...
        cache.remove(networkRequest);
        ...
      }
    }
    
    public static boolean invalidatesCache(String method) {
      return method.equals("POST")
          || method.equals("PATCH")
          || method.equals("PUT")
          || method.equals("DELETE")
          || method.equals("MOVE");
    }
    
  3. 默认gzip压缩

    // Range 告知服务器返回文件的哪一部分
    if (userRequest.header("Accept-Encoding") == null && userRequest.header("Range") == null) {
    transparentGzip = true;
    requestBuilder.header("Accept-Encoding", "gzip");
    }
    

gzip

  1. 自定义cookieJar

    cookieJar的处理过程(源码)

    // 加载cookie
    List<Cookie> cookies = cookieJar.loadForRequest(userRequest.url());
    if (!cookies.isEmpty()) {
        requestBuilder.header("Cookie", cookieHeader(cookies));
    }
    Response networkResponse = chain.proceed(requestBuilder.build());
    // 请求完成,保存cookie
    HttpHeaders.receiveHeaders(cookieJar, userRequest.url(), networkResponse.headers());
    

    自定义cookieJar方式

    public class MyCookieJar implements CookieJar {
        @Override
        public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
           // 服务端返回的 cookie,可保存在本地
        }
        @Override
        public List<Cookie> loadForRequest(HttpUrl url) {
            // 从本地加载保存的 cookie
            return null;
        }
    }
    // 设置自定义 CookieJar
    OKHttpClient.Build().cookieJar(new MyCookieJar());
    
  2. forWebSocket
    RealCall.getResponseWithInterceptorChain添加拦截器时,有一个forWebSocket,它在什么时候是true/false

if (!forWebSocket) {
interceptors.addAll(client.networkInterceptors());
}

forWebSocket是创建RealCall对象构造函数传的参数,我们平时使用传false,使用WebSocket时传false,也就是调用okHttpClient.newWebSocket时。
也就是说,使用WebSocket时,不支持addNetWorkInterceptor.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值