Retrofit源码阅读

前言

  • 为什么要看Retrofit源码?

    • 因为目前项目使用的Retrofit网络请求。想去详细了解下。
  • 这次阅读重点关注的点通过Create方法追踪工作流程

    • 如何进行线程切换
    • 用到反射如何去优化性能的
    • 怎么解析参数和注解的
    • 它针对Kotlin做哪些处理
  • 本次阅读源码版本依赖

    • implementation 'com.squareup.retrofit2:retrofit:2.9.0'
      implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'
      
  • 分析不对的地方请指出。。。

  • 来张图

    retrofit.png

Retrofit 基本使用

  • 创建接口

    用于存放请求地址参数信息

    interface ApiService {
        @GET("users/{user}/repos")
        fun listRepos(@Path("user") user: String?): Call?
    }
    
  • 发起请求与Retrofit配置

    class MainActivity : AppCompatActivity(), View.OnClickListener {
        private var mApiService: ApiService? = null
    
        private var mBinding: ActivityMainBinding? = null
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            mBinding = ActivityMainBinding.inflate(layoutInflater)
            setContentView(mBinding?.root)
            mBinding?.tvData?.setOnClickListener(this)
            //retrofit配置
            val retrofit = Retrofit.Builder()
                .baseUrl("https://api.github.com/")
                .build()
           //接口实例
            mApiService = retrofit.create(ApiService::class.java)
        }
    
        override fun onClick(v: View?) {
            requestData()
        }
       
        //发起请求
        private fun requestData() {
            mApiService?.listRepos("brycecui")?.enqueue(object : Callback {
                override fun onResponse(call: Call, response: Response) {
                    Log.e("MainActivity", "onResponse:${response.body().toString()}")
                }
    
                override fun onFailure(call: Call, t: Throwable) {
                    Log.e("MainActivity", "onFailure${t.localizedMessage}")
                }
    
            })
        }
    
    }
    

问题分析

Create方法源码

public  T create(final Class service) {
  validateServiceInterface(service);
  return (T)
      Proxy.newProxyInstance(
          service.getClassLoader(),
          new Class[] {service},
          new InvocationHandler() {
            //注释①
            private final Platform platform = Platform.get();
            private final Object[] emptyArgs = new Object[0];

            @Override
            public @Nullable 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);
              }
              args = args != null ? args : emptyArgs;
              //注释②
              return platform.isDefaultMethod(method)
                  ? platform.invokeDefaultMethod(method, service, proxy, args)
                  : loadServiceMethod(method).invoke(args);
            }
          });
}
  • 注释①。获取对应平台

    • private static final Platform PLATFORM = findPlatform();
      
      static Platform get() {
        return PLATFORM;
      }
      
      //得到Android平台
      private static Platform findPlatform() {
        return "Dalvik".equals(System.getProperty("java.vm.name"))
            ? new Android() //
            : new Platform(true);
      }
      //省略部分代码
        static final class Android extends Platform {
          Android() {
            super(Build.VERSION.SDK_INT >= 24);
          }
          @Override
          public Executor defaultCallbackExecutor() {
            return new MainThreadExecutor();
          }
      //省略部分代码
          
          static final class MainThreadExecutor implements Executor {
            private final Handler handler = new Handler(Looper.getMainLooper());
      
            @Override
            public void execute(Runnable r) {
              //切换线程
              handler.post(r);
            }
          }
        }
      

      会得到一个Android平台。

  • 注释②。会返回false走到loadServiceMethod方法

    • 看下loadServiceMethod源码

      private final Map> serviceMethodCache = new ConcurrentHashMap<>();
      ServiceMethod loadServiceMethod(Method method) {
        ServiceMethod result = serviceMethodCache.get(method);
        if (result != null) return result;
      
        synchronized (serviceMethodCache) {
          result = serviceMethodCache.get(method);
          if (result == null) {
            //解析数据得到ServiceMethod
            result = ServiceMethod.parseAnnotations(this, method);
            serviceMethodCache.put(method, result);
          }
        }
        return result;
      }
      

      如果(线程安全的ConcurrentHashMap)缓存中有直接返回。没有解析并储存之后返回ServiceMethod

    • 看下他解析数据的过程源码

      abstract class ServiceMethod {
        static  ServiceMethod parseAnnotations(Retrofit retrofit, Method method) {
          
          RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
      
          //省略部分代码
          
          return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
        }
      
        abstract @Nullable T invoke(Object[] args);
      }
      

      ServiceMethod是一个抽象类。

      • RequestFactory的parseAnnotations源码

        //建造者模式
        static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
          return new Builder(retrofit, method).build();
        }
        
        
      • RequestFactory构造方法

        RequestFactory(Builder builder) {
          method = builder.method;
          baseUrl = builder.retrofit.baseUrl;
          httpMethod = builder.httpMethod;
          relativeUrl = builder.relativeUrl;
          headers = builder.headers;
          contentType = builder.contentType;
          hasBody = builder.hasBody;
          isFormEncoded = builder.isFormEncoded;
          isMultipart = builder.isMultipart;
          parameterHandlers = builder.parameterHandlers;
          isKotlinSuspendFunction = builder.isKotlinSuspendFunction;
        }
        
      • RequestFactory.Builder和它的build方法

         Builder(Retrofit retrofit, Method method) {
              this.retrofit = retrofit;
              this.method = method;
           //通过 反射得到注解、参数等信息。
              this.methodAnnotations = method.getAnnotations();
              this.parameterTypes = method.getGenericParameterTypes();
              this.parameterAnnotationsArray = method.getParameterAnnotations();
            }
        RequestFactory build() {
          for (Annotation annotation : methodAnnotations) {
            parseMethodAnnotation(annotation);
          }
          int parameterCount = parameterAnnotationsArray.length;
          parameterHandlers = new ParameterHandler[parameterCount];
          for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) {
            parameterHandlers[p] =
                parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
          }
          //省略部分空检查代码
          return new RequestFactory(this);
        }
        
      • 我看看下返回的RequestFactory都有啥。看下图是使用上面简单使用的例子debug的


        retrofit-debug

        baseUrl:就是retrofit传过来的baseUrl

        httpMethod:我们用的GET注解。(用的POST就是POST)我们可以看下如何进行解析的

        private void parseMethodAnnotation(Annotation annotation) {
          if (annotation instanceof DELETE) {
            parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
          } else if (annotation instanceof GET) {
            parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
          } else if (annotation instanceof HEAD) {
            parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
          } else if (annotation instanceof PATCH) {
            parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
          } else if (annotation instanceof POST) {
            parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
          } else if (annotation instanceof PUT) {
            parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
          } else if (annotation instanceof OPTIONS) {
            parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
          } else if (annotation instanceof HTTP) {
            HTTP http = (HTTP) annotation;
            parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
          } else if (annotation instanceof retrofit2.http.Headers) {
            String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
            if (headersToParse.length == 0) {
              throw methodError(method, "@Headers annotation is empty.");
            }
            headers = parseHeaders(headersToParse);
          } else if (annotation instanceof Multipart) {
            if (isFormEncoded) {
              throw methodError(method, "Only one encoding annotation is allowed.");
            }
            isMultipart = true;
          } else if (annotation instanceof FormUrlEncoded) {
            if (isMultipart) {
              throw methodError(method, "Only one encoding annotation is allowed.");
            }
            isFormEncoded = true;
          }
        }
        

        根据使用instanceof 判断是那种注解进行对应的方法解析。也就是parseHttpMethodAndPath方法。

        private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
          //省略httpMethod空异常检查
          this.httpMethod = httpMethod;
          this.hasBody = hasBody;
          if (value.isEmpty()) {
            return;
          }
          // Get the relative URL path and existing query string, if present.
          int question = value.indexOf('?');
          if (question != -1 && question < value.length() - 1) {
            // Ensure the query string does not have any named parameters.
            String queryParams = value.substring(question + 1);
            Matcher queryParamMatcher = PARAM_URL_REGEX.matcher(queryParams);
            if (queryParamMatcher.find()) {
              throw methodError(
                  method,
                  "URL query string \"%s\" must not have replace block. "
                      + "For dynamic query parameters use @Query.",
                  queryParams);
            }
          }
        
          this.relativeUrl = value;
          this.relativeUrlParamNames = parsePathParameters(value);
        }
        /***********************************手动分割线******************************************/
        static Set parsePathParameters(String path) {
              Matcher m = PARAM_URL_REGEX.matcher(path);
              Set patterns = new LinkedHashSet<>();
              while (m.find()) {
                patterns.add(m.group(1));
              }
              return patterns;
            }
        

        parseHttpMethodAndPath 的value是 请求方法注解里面的值。对应示例中是users/{user}/repos。由于没有所以不会走if语句。

        relativeUrl也就等于users/{user}/repos

  • 在看下ServiceMethod返回的HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory)方法

    static  HttpServiceMethod parseAnnotations(
        Retrofit retrofit, Method method, RequestFactory requestFactory) {
      boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
      boolean continuationWantsResponse = false;
      boolean continuationBodyNullable = false;
      Annotation[] annotations = method.getAnnotations();
      Type adapterType;
      if (isKotlinSuspendFunction) {
        Type[] parameterTypes = method.getGenericParameterTypes();
        Type responseType = Utils.getParameterLowerBound(0, (ParameterizedType) parameterTypes[parameterTypes.length - 1]);
        if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
          // Unwrap the actual body type from Response.
          responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
          continuationWantsResponse = true;
        } else {
          // TODO figure out if type is nullable or not
          // Metadata metadata = method.getDeclaringClass().getAnnotation(Metadata.class)
          // Find the entry for method
          // Determine if return type is nullable or not
        }
        adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
        annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
      } else {
        adapterType = method.getGenericReturnType();
      }
    
      CallAdapter callAdapter = createCallAdapter(retrofit, method, adapterType, annotations);
      Type responseType = callAdapter.responseType();
      
      Converter responseConverter = createResponseConverter(retrofit, method, responseType);
    
      okhttp3.Call.Factory callFactory = retrofit.callFactory;
      if (!isKotlinSuspendFunction) {
        return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
      } else if (continuationWantsResponse) {
        //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
        return (HttpServiceMethod)
            new SuspendForResponse<>(
                requestFactory,
                callFactory,
                responseConverter,
                (CallAdapter>) callAdapter);
      } else {
        //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
        return (HttpServiceMethod)
            new SuspendForBody<>(
                requestFactory,
                callFactory,
                responseConverter,
                (CallAdapter>) callAdapter,
                continuationBodyNullable);
      }
    }
    

    isKotlinSuspendFunction用来判断是否使用kotlin协程请求。

    true代表使用挂起函数。那么会创建SuspendForResponse和SuspendForBody。分别是返回值为Ressponse和ResponseBody。

    分别在内部调用了扩展函数。使用协程切换线程

    //返回值为Ressponse使用
    suspend fun  Call.awaitResponse(): Response {
      return suspendCancellableCoroutine { continuation ->
        continuation.invokeOnCancellation {
          cancel()
        }
        enqueue(object : Callback {
          override fun onResponse(call: Call, response: Response) {
            continuation.resume(response)
          }
    
          override fun onFailure(call: Call, t: Throwable) {
            continuation.resumeWithException(t)
          }
        })
      }
    }
    //返回值为ResponseBody使用。成功直接返回ResponseBody
    suspend fun  Call.await(): T {
      return suspendCancellableCoroutine { continuation ->
        continuation.invokeOnCancellation {
          cancel()
        }
        enqueue(object : Callback {
          override fun onResponse(call: Call, response: Response) {
            if (response.isSuccessful) {
              val body = response.body()
              if (body == null) {
                val invocation = call.request().tag(Invocation::class.java)!!
                val method = invocation.method()
                val e = KotlinNullPointerException("Response from " +
                    method.declaringClass.name +
                    '.' +
                    method.name +
                    " was null but response body type was declared as non-null")
                continuation.resumeWithException(e)
              } else {
                continuation.resume(body)
              }
            } else {
              continuation.resumeWithException(HttpException(response))
            }
          }
    
          override fun onFailure(call: Call, t: Throwable) {
            continuation.resumeWithException(t)
          }
        })
      }
    }
    

    最终会返回一个CallAdapted<>,而CallAdapted<>是继承的HttpServiceMethod。

    static final class CallAdapted extends HttpServiceMethod {
      private final CallAdapter callAdapter;
      CallAdapted(
          RequestFactory requestFactory,
          okhttp3.Call.Factory callFactory,
          Converter responseConverter,
          CallAdapter callAdapter) {
        super(requestFactory, callFactory, responseConverter);
        this.callAdapter = callAdapter;
      }
    
      @Override
      protected ReturnT adapt(Call call, Object[] args) {
        return callAdapter.adapt(call);
      }
    }
    
                            而loadServiceMethod(method)的invoke(args)方法。会调用CallAdapted的adapte方法。而这个CallAdapted是由HttpServiceMethod的 createCallAdapter方法创建的。也就是retrofit的addCallAdapterFactory方法添加的。示例中我们没有添加所以走得是默认的CallAdapted。在retrofit的Builder类中可以找到
    
List callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
//这添加一个平台默认的CallAdapter并且传一个线程池callbackExecutor
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
//可以看到defaultCallbackExecutor也是由平台默认的额
 Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

我们看下平台platform这俩个默认方法。

List defaultCallAdapterFactories(
    @Nullable Executor callbackExecutor) {
  DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
  return hasJava8Types
      ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
      : singletonList(executorFactory);
}

继续看DefaultCallAdapterFactory

final class DefaultCallAdapterFactory extends CallAdapter.Factory {
  private final @Nullable Executor callbackExecutor;

  DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
    this.callbackExecutor = callbackExecutor;
  }

  @Override
  public @Nullable CallAdapter get(
      Type returnType, Annotation[] annotations, Retrofit retrofit) {
//省略空检查
    final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);

    final Executor executor =
        Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
            ? null
            : callbackExecutor;

    return new CallAdapter>() {
      @Override
      public Type responseType() {
        return responseType;
      }

      @Override
      public Call adapt(Call call) {
        //当时kotlin协程请求时返回okhttpcall 否则返回ExecutorCallbackCall
        return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
      }
    };
  }

  static final class ExecutorCallbackCall implements Call {
    final Executor callbackExecutor;
    final Call delegate;

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

    @Override
    public void enqueue(final Callback callback) {
      Objects.requireNonNull(callback, "callback == null");

      //(OkHttp封装类)OkHttpCall的enqueue方法进行请求
      delegate.enqueue(
          new Callback() {
            @Override
            public void onResponse(Call call, final Response response) {
              //线程切换
              callbackExecutor.execute(
                  () -> {
                    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 call, final Throwable t) {
              callbackExecutor.execute(() -> callback.onFailure(ExecutorCallbackCall.this, t));
            }
          });
    }

    @Override
    public boolean isExecuted() {
      return delegate.isExecuted();
    }

    @Override
    public Response execute() throws IOException {
      return delegate.execute();
    }

    @Override
    public void cancel() {
      delegate.cancel();
    }

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

    @SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
    @Override
    public Call clone() {
      return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
    }

    @Override
    public Request request() {
      return delegate.request();
    }

    @Override
    public Timeout timeout() {
      return delegate.timeout();
    }
  }
}

也就是说我们示例中的mApiService?.listRepos("brycecui")?.enqueue()最终到了这里。delegate他是 Call接口。它的实现类是OkHttpCall。怎么知道不是别的实现类。上面我们通过代码追踪知道了loadserviceMethod.invoke.实际是调用了 抽象类ServiceMethod的实现类HttpServiceMethod的invoke方法。也就是下面这个方法。下面调用了adapt方法并把OkHttpCall传了过去。最终也就是通过DefaultCallAdapterFactory的get方法的adapt创建一个ExecutorCallbackCall传递的。

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

看下 callbackExecutor.execute。线程切换关键所在。

static final class MainThreadExecutor implements Executor {
  private final Handler handler = new Handler(Looper.getMainLooper());
  @Override
  public void execute(Runnable r) {
    handler.post(r);
  }
}

也就是使用handler.post(r);切换到主线程。

总结

  • 如何切换线程

    • kotlin 使用协程
    • 默认使用handler
  • 用到反射如何优化性能的

    • 使用map缓存避免多次反射浪费性能
  • 如何解析参数注解

    • 使用反射解析、正则匹配
  • 针对kotlin做了哪些处理

    • 判断是否使用kotlin并且针对返回值是否只需要body

你可能感兴趣的:(Retrofit源码阅读)