Retrofitソースコード解析ノット

8552 ワード

1、Retrofit retrofit=new Retrofit.Builder() .baseUrl(url).addConverterFactory(GsonConverterFactory.create()) .build()入手:
public Retrofit build() {
    if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");  //baseUrl null 
    }

    okhttp3.Call.Factory callFactory = this.callFactory;
    if (callFactory == null) {   // OK 
        callFactory = new OkHttpClient();
    }

    Executor callbackExecutor = this.callbackExecutor;
    if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
    }

    // Make a defensive copy of the adapters and add the default Call adapter.
    List adapterFactories = new ArrayList<>(this.adapterFactories);
    adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

    // Make a defensive copy of the converters.
    List converterFactories = new ArrayList<>(this.converterFactories);

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

上を通るとRetrofitが作成され、次にIpService ipService=retrofit.create(IpServices.class)、つまりcreate:
public  T create(final Class service) {
    Utils.validateServiceInterface(service);  // , , 
    if (validateEagerly) {  // false
    eagerlyValidateMethods(service);   // service 
    }
    // , ,Proxy.newProxyInstance Android 
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class>[] { service },
        new InvocationHandler() {
        private final Platform platform = Platform.get();
         // Retrofit service , , , 
        @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);
            }
            ServiceMethod serviceMethod =
                (ServiceMethod) loadServiceMethod(method);
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
        }
        });
}

任意のメソッドを呼び出し、最後に上のinvokeに進みます.loadServiceMethodを見てください.
ServiceMethod, ?> loadServiceMethod(Method method) {
    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();  // Method ServiceMethod
        serviceMethodCache.put(method, result);
    }
    }
    return result;
}

result=new ServiceMethod.Builder<>(this, method).build():
public ServiceMethod build() {
    callAdapter = createCallAdapter();   //1, 
    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?");
    }
    responseConverter = createResponseConverter();

    for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);    // , httpMethod  
    }

    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);
        }

        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);
    }

上の注記1では、createCallAdapter:
private CallAdapter 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
    // ExecutorCallAdapterFactory get , 
    return (CallAdapter) 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);
  }
}

ExecutorCallAdapterFactoryのget:
@Override
public CallAdapter, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
  return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter>() {
  @Override public Type responseType() {
    return responseType;      // Call, MyData
  }

  @Override public Call adapt(Call call) {
    return new ExecutorCallbackCall<>(callbackExecutor, call);  // call UI 
  }
};
}

Retrofitのcreateメソッドに戻り、最後にこのステップを実行します.callAdapter.adapt(okHttpCall)は、実際にExecutorCallbackCallに戻ったことを分析し、ExecutorCallbackCallの実行方法を見ています.
@Override 
public void enqueue(final Callback callback) {
  checkNotNull(callback, "callback == null");
   // OKHttp newCall.enqueue
  delegate.enqueue(new Callback() {
    @Override public void onResponse(Call call, final Response response) {
      callbackExecutor.execute(new Runnable() {
        @Override public void run() {
          if (delegate.isCanceled()) {
            // ,callback 
            // 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(new Runnable() {
        @Override public void run() {
          callback.onFailure(ExecutorCallbackCall.this, t);
        }
      });
    }
  });
}

最後に、retrofitはJavaのProxyクラスを通じて動的エージェントの関連エージェントを完了し、インタフェースの実装クラスを取得し、invokeメソッドの内部で、私たちが宣言した注釈や実パラメータなどを取得し、ServiceMethodを構築し、ServiceMethodで大量の情報を解析し、最後にOKHttpリクエストを通じてUIスレッドのコールバックを処理します.