Retrofit是Square開源的一個適用於Android和Java的類型安全的HTTP網絡框架。其本質是對OKHttp的進一步封裝,經過接口的方式進行網絡請求,結合了註解、動態代理等技術實現模塊解耦,簡化了網絡請求的上層邏輯。從Android4.4開始,http的底層實現已替換成了OKHttp,Retrofit也所以成爲了Android平臺上主流的網絡框架之一。
http://square.github.io/retro...git
Step1:聲明Retrofit API請求接口github
public interface GitHub { @GET("/repos/{owner}/{repo}/contributors") Call<List<Contributor>> contributors( @Path("owner") String owner, @Path("repo") String repo); }
Step2:構建Retrofit對象並建立API接口實例api
// Create a very simple REST adapter which points the GitHub API. Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com") .addConverterFactory(GsonConverterFactory.create()) .build(); // Create an instance of our GitHub API interface. GitHub github = retrofit.create(GitHub.class);
Step3:經過API接口方法建立Call實例併發起請求安全
// Create a call instance for looking up Retrofit contributors. Call<List<Contributor>> call = github.contributors("square", "retrofit"); // Fetch and print a list of the contributors to the library. List<Contributor> contributors = call.execute().body();
Retrofit的實現就是這麼簡單優雅,業務層只須要像調用普通接口同樣便可完成網絡請求。網絡
首先要構建一個Retrofit實例,其做用是把接口方法註解轉換爲OKHttp請求。
Retrofit.Builder.build併發
public Retrofit build() { if (baseUrl == null) { throw new IllegalStateException("Base URL required."); } okhttp3.Call.Factory callFactory = this.callFactory; if (callFactory == null) { 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<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories); 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); } }
Retrofit實例化完成,建立API接口動態代理實現。
Retrofit.createapp
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(); @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<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method); OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args); return serviceMethod.adapt(okHttpCall); } }); }
接口動態代理建立完成,開始執行網絡請求。
OKHttpCall.execute框架
@Override public Response<T> execute() throws IOException { okhttp3.Call call; synchronized (this) { if (executed) throw new IllegalStateException("Already executed."); executed = true; if (creationFailure != null) { if (creationFailure instanceof IOException) { throw (IOException) creationFailure; } else if (creationFailure instanceof RuntimeException) { throw (RuntimeException) creationFailure; } else { throw (Error) creationFailure; } } call = rawCall; if (call == null) { try { call = rawCall = createRawCall(); } catch (IOException | RuntimeException | Error e) { throwIfFatal(e); // Do not assign a fatal error to creationFailure. creationFailure = e; throw e; } } } if (canceled) { call.cancel(); } return parseResponse(call.execute()); }
ExecutorCallbackCall把網絡請求委派給OKHttpCall,後者主要負責:
1. ServiceMethod.toCall負責將註解參數轉換爲okhttp3.Callide
/** Builds an HTTP request from method arguments. */ okhttp3.Call toCall(@Nullable Object... args) throws IOException { RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers, contentType, hasBody, isFormEncoded, isMultipart); @SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types. ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers; int argumentCount = args != null ? args.length : 0; if (argumentCount != handlers.length) { throw new IllegalArgumentException("Argument count (" + argumentCount + ") doesn't match expected count (" + handlers.length + ")"); } for (int p = 0; p < argumentCount; p++) { handlers[p].apply(requestBuilder, args[p]); } return callFactory.newCall(requestBuilder.build()); }
2. OkHttpCall.parseResponse負責Response解析及請求結果狀態的封裝回調。ui
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 { 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; } }
3. ServiceMethod.toResponse負責將ResponseBody轉換爲接口返回數據類型。
*其內部Converter接口負責把HTTP請求響應結果轉換可識別的數據格式。舉個栗子:*
/** Builds a method return value from an HTTP response body. */ R toResponse(ResponseBody body) throws IOException { return responseConverter.convert(body); }
ExecutorCallbackCall.execute同步請求完以後,直接取出responseConverter轉換出來的body即爲請求結果。
// Fetch and print a list of the contributors to the library. List<Contributor> contributors = call.execute().body();
到此,一個Retrofit GET同步請求流程基本分析完了。想要加深理解,Read the fucking source code!