倒霉的菜鸟

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Retrofit是对okhttp的包装, 先看下简单使用:

1, 引入依赖

1 implementation 'com.squareup.retrofit2:retrofit:2.9.0'
2 implementation 'com.squareup.retrofit2:converter-gson:2.9.0'

这里的converter-gson是接收到response后做gson解析用的

2, 定义一个service接口, 使用注解的方式声明请求方法,参数等 

1 interface MyService {
2 
3     @GET("users/{user}/repos")
4     fun testGet(@Path("user") user : String): Call<ResponseData>
5 }

3, 创建retrofit

1 val retrofit = Retrofit.Builder()
2             .baseUrl("https://www.baidu.com")
3             .addConverterFactory(GsonConverterFactory.create())
4             .build()

4, 通过retrofit.create()方法创建出service的实例

1 val service = retrofit.create(MyService::class.java)
2       

 

5, 通过这个service实例创建一个可以用来发起网络请求的Call对象

1   val call: Call<ResponseData> = service.testGet("zhangsan")

6, call.enqueue(callback)执行网络请求, 这里也可以用call.execute(), 区别在于enqueue是异步的 

1 call.enqueue(object : Callback<ResponseData>{
2             override fun onResponse(call: Call<ResponseData>, response: Response<ResponseData>) {
3                 println(response.body()?.name)
4             }
5 
6             override fun onFailure(call: Call<ResponseData>, t: Throwable) {
7                 t.printStackTrace()
8             }
9         })

 

Retrofit源码概述:

1, create()方法主要做了两件事, 

首先验证我们传进去的这个service是不是个接口,不是就抛异常,

以及这个接口及其父接口是不是包含了泛型(java8的特性), 如果是就会抛出异常

以及接口里的方法是不是静态方法(java8), 接口里的方法是不是有默认实现(java8)

其次,通过动态代理的方式生成一个service接口的实现

(代理: 简单来说, 比如一个类实现了某个接口, 那么我们就说这个类是这个接口的代理。 所谓动态代理就是说,这个实现类并不是我们预先写好的, 而是在程序运行期间动态去生成的。)

 1 public <T> T create(final Class<T> service) {
 2     validateServiceInterface(service);
 3     return (T)
 4         Proxy.newProxyInstance(
 5             service.getClassLoader(),
 6             new Class<?>[] {service},
 7             new InvocationHandler() {
 8               private final Platform platform = Platform.get();
 9               private final Object[] emptyArgs = new Object[0];
10 
11               @Override
12               public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args)
13                   throws Throwable {
14                 // If the method is a method from Object then defer to normal invocation.
15                 if (method.getDeclaringClass() == Object.class) {
16                   return method.invoke(this, args);
17                 }
18                 args = args != null ? args : emptyArgs;
19                 return platform.isDefaultMethod(method)
20                     ? platform.invokeDefaultMethod(method, service, proxy, args)
21                     : loadServiceMethod(method).invoke(args);
22               }
23             });
24   }

InvocationHandler的invoke方法里传入了method, 这个method就是我们在service里定义的那些方法, 程序运行过程中会通过反射来获取

2, loadServiceMethod这里主要是用了cache, 如果map里有,就从map去拿, 否则就通过parseAnnotations()方法来获取一个ServiceMethod对象

 1 ServiceMethod<?> loadServiceMethod(Method method) {
 2     ServiceMethod<?> result = serviceMethodCache.get(method);
 3     if (result != null) return result;
 4 
 5     synchronized (serviceMethodCache) {
 6       result = serviceMethodCache.get(method);
 7       if (result == null) {
 8         result = ServiceMethod.parseAnnotations(this, method);
 9         serviceMethodCache.put(method, result);
10       }
11     }
12     return result;
13   }

点进去看看, 首先通过RequestFactory.parseAnnotations(retrofit, method)得到一个requestFactory对象, 然后HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory)

 1 static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
 2     RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
 3 
 4     Type returnType = method.getGenericReturnType();
 5     if (Utils.hasUnresolvableType(returnType)) {
 6       throw methodError(
 7           method,
 8           "Method return type must not include a type variable or wildcard: %s",
 9           returnType);
10     }
11     if (returnType == void.class) {
12       throw methodError(method, "Service methods cannot return void.");
13     }
14 
15     return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
16   }

RequestFactory.parseAnnotations(retrofit, method)这个方法主要是去解析我们在service里加的那些注解, 获取Http请求需要的一些信息,比如: header, body等等 

1 static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
2     return new Builder(retrofit, method).build();
3   }
1 RequestFactory build() {
2       for (Annotation annotation : methodAnnotations) {
3         parseMethodAnnotation(annotation);
4       }
 1 private void parseMethodAnnotation(Annotation annotation) {
 2       if (annotation instanceof DELETE) {
 3         parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
 4       } else if (annotation instanceof GET) {
 5         parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
 6       } else if (annotation instanceof HEAD) {
 7         parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
 8       } else if (annotation instanceof PATCH) {
 9         parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
10       } else if (annotation instanceof POST) {
11         parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
12       } else if (annotation instanceof PUT) {
13         parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
14       } else if (annotation instanceof OPTIONS) {
15         parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
16       } else if (annotation instanceof HTTP) {
17         HTTP http = (HTTP) annotation;
18         parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
19       } else if (annotation instanceof retrofit2.http.Headers) {
20         String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
21         if (headersToParse.length == 0) {
22           throw methodError(method, "@Headers annotation is empty.");
23         }
24         headers = parseHeaders(headersToParse);
25       } else if (annotation instanceof Multipart) {
26         if (isFormEncoded) {
27           throw methodError(method, "Only one encoding annotation is allowed.");
28         }
29         isMultipart = true;
30       } else if (annotation instanceof FormUrlEncoded) {
31         if (isMultipart) {
32           throw methodError(method, "Only one encoding annotation is allowed.");
33         }
34         isFormEncoded = true;
35       }
36     }

 

3, 接下来重点看看HttpServiceMethod类, 它里面实现了invoke()方法,

1 @Override
2   final @Nullable ReturnT invoke(Object[] args) {
3     Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
4     return adapt(call, args);
5   }

 

 OkHttpCall 是 retrofit2.Call 的⼦类。上面的第一行代码负责将 ServiceMethod 解读到的信息(主要是⼀个 RequestFactory 、⼀个 OkHttpClient 和⼀个 ResponseConverter )封装进 OkHttpCall ; ⽽这个对象可以在需要的时候(例如它的 enqueue() ⽅法被调⽤的时候), 利⽤ RequestFactory 和 OkHttpClient 来创建⼀个 okhttp3.Call 对象,并调⽤这个 okhttp3.Call 对象来进⾏⽹络请求的发起,然后利⽤ ResponseConverter 对结果进⾏预处理之后,交回给 Retrofit 的 Callback

 

1     protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
2       return callAdapter.adapt(call);
3     }

callAdapter一直往进跟, 发现这里就是我们从retrofit.Builder().addAdapterFactory(adapter)这里传进来的这个adapter

 1 public CallAdapter<?, ?> nextCallAdapter(
 2       @Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) {
 3     Objects.requireNonNull(returnType, "returnType == null");
 4     Objects.requireNonNull(annotations, "annotations == null");
 5 
 6     int start = callAdapterFactories.indexOf(skipPast) + 1;
 7     for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
 8       CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
 9       if (adapter != null) {
10         return adapter;
11       }
12     }

 

adapt⽅法会使⽤⼀个 CallAdapter 对象来把 OkHttpCall 对象进⾏转换,⽣成⼀个新 的对象。

默认情况下,callAdapter返回的是⼀个 ExecutorCallbackCall ,它的作⽤是把操 作切回主线程后再交给 Callback 。 另外,如果有⾃定义的 CallAdapter,这⾥也可以⽣成别的类型的对象,例如 RxJava 的 Observable ,来让 Retrofit 可以和 RxJava 结合使⽤。

 

 

小结retrofit的关键实现:

1, 通过动态代理的方式为我们定义的接口生成一个实现类

2, 通过RequestFactory对我们接口中定义的注解进行解析,得到http请求需要的一些参数

3, 封装了okhttpCall去实现具体的网络请求

4, 通过convertFactory将请求返回的字节流转换成我们需要的格式,如json

5, 请求完成后,通过adapterFactory完成线程的切换, callAdapter默认返回的是⼀个 ExecutorCallbackCall ,它的作⽤是把操 作切回主线程, 我们也可以在创建retrofit时把它换成其他adapter, 比如RxJava的Observable 

 

posted on 2021-10-21 16:14  倒霉的菜鸟  阅读(353)  评论(0编辑  收藏  举报