2.Retrofit的建立流程源碼分析php
3.建立ServiceMethod流程源碼分析java
4.註解的解析android
5.OkHttpCall的建立源碼分析git
6.OkHttpCall的網絡請求github
0.1.1 網絡傳輸都是二進制流,那麼解析數據時,如何經過ServiceMethod使用Converter轉換成Java對象進行數據解析面試
//AdvertCommon是javabean實體類,並無序列化,那麼網絡解析數據如何解析java對象呢? Call<AdvertCommon> getSplashImage(@Query("type") int type);
0.1.2 以下所示,爲何說apiService對象其實是動態代理對象,而不是真正的網絡請求接口建立的對象json
ApiService apiService = retrofit.create(ApiService.class);
Api接口segmentfault
public interface DouBookApi { /** * 根據tag獲取圖書 * @param tag 搜索關鍵字 * @param count 一次請求的數目 最多100
*/ @GET("v2/book/search") Observable<DouBookBean> getBook(@Query("tag") String tag, @Query("start") int start, @Query("count") int count); } ```
Model類設計模式
public class DouBookModel { private static DouBookModel bookModel; private DouBookApi mApiService; public DouBookModel(Context context) { mApiService = RetrofitWrapper .getInstance(ConstantALiYunApi.API_DOUBAN) //baseUrl地址 .create(DouBookApi.class); } public static DouBookModel getInstance(Context context){ if(bookModel == null) { bookModel = new DouBookModel(context); } return bookModel; } public Observable<DouBookBean> getHotMovie(String tag, int start , int count) { Observable<DouBookBean> book = mApiService.getBook(tag, start, count); return book; } }
抽取類api
public class RetrofitWrapper { private static RetrofitWrapper instance; private Retrofit mRetrofit; public RetrofitWrapper(String url) { OkHttpClient.Builder builder = new OkHttpClient.Builder(); //打印日誌 HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); logging.setLevel(HttpLoggingInterceptor.Level.BODY); builder.addInterceptor(logging).build(); OkHttpClient client = builder.addInterceptor(new LogInterceptor("HTTP")).build(); //解析json Gson gson = new GsonBuilder() .setLenient() .create(); mRetrofit = new Retrofit .Builder() .baseUrl(url) .addConverterFactory(GsonConverterFactory.create(gson)) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .client(client) .build(); } public static RetrofitWrapper getInstance(String url){ //synchronized 避免同時調用多個接口,致使線程併發 synchronized (RetrofitWrapper.class){ instance = new RetrofitWrapper(url); } return instance; } public <T> T create(final Class<T> service) { return mRetrofit.create(service); } }
使用
DouBookModel model = DouBookModel.getInstance(activity); model.getHotMovie(mType,start,count) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Subscriber<DouBookBean>() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(DouBookBean bookBean) { } });
針對Retrofit,須要注意
首先看看裏面的源代碼,以下所示
//第一步 public Builder() { this(Platform.get()); } //第二步,追蹤到Platform類中 private static final Platform PLATFORM = findPlatform(); static Platform get() { return PLATFORM; } private static Platform findPlatform() { try { Class.forName("android.os.Build"); if (Build.VERSION.SDK_INT != 0) { //此處表示:若是是Android平臺,就建立並返回一個Android對象 return new Android(); } } catch (ClassNotFoundException ignored) { } try { Class.forName("java.util.Optional"); return new Java8(); } catch (ClassNotFoundException ignored) { } return new Platform(); }
而後看一下new Android()是作了什麼?
static class Android extends Platform { @Override public Executor defaultCallbackExecutor() { // 返回一個默認的回調方法執行器 // 該執行器做用:切換線程(子->>主線程),並在主線程(UI線程)中執行回調方法 return new MainThreadExecutor(); } @Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) { if (callbackExecutor == null) throw new AssertionError(); // 建立默認的網絡請求適配器工廠 // 該默認工廠生產的 adapter 會使得Call在異步調用時在指定的 Executor 上執行回調 // 採用了策略模式 return new ExecutorCallAdapterFactory(callbackExecutor); } static class MainThreadExecutor implements Executor { // 獲取與Android 主線程綁定的Handler private final Handler handler = new Handler(Looper.getMainLooper()); @Override public void execute(Runnable r) { // 該Handler是上面獲取的與Android 主線程綁定的Handler // 在UI線程進行對網絡請求返回數據處理等操做。 handler.post(r); } } }
都知道這個方法主要是設置baseUrl。源碼以下所示
public Builder baseUrl(String baseUrl) { checkNotNull(baseUrl, "baseUrl == null"); HttpUrl httpUrl = HttpUrl.parse(baseUrl); if (httpUrl == null) { throw new IllegalArgumentException("Illegal URL: " + baseUrl); } return baseUrl(httpUrl); }
HttpUrl是如何解析url,對url有什麼條件,來看一下parse方法源碼
public static @Nullable HttpUrl parse(String url) { Builder builder = new Builder(); Builder.ParseResult result = builder.parse(null, url); return result == Builder.ParseResult.SUCCESS ? builder.build() : null; } ParseResult parse(@Nullable HttpUrl base, String input) { int pos = skipLeadingAsciiWhitespace(input, 0, input.length()); int limit = skipTrailingAsciiWhitespace(input, pos, input.length()); // Scheme. int schemeDelimiterOffset = schemeDelimiterOffset(input, pos, limit); if (schemeDelimiterOffset != -1) { if (input.regionMatches(true, pos, "https:", 0, 6)) { this.scheme = "https"; pos += "https:".length(); } else if (input.regionMatches(true, pos, "http:", 0, 5)) { this.scheme = "http"; pos += "http:".length(); } else { return ParseResult.UNSUPPORTED_SCHEME; // Not an HTTP scheme. } } else if (base != null) { this.scheme = base.scheme; } else { return ParseResult.MISSING_SCHEME; // No scheme. } //下面代碼省略了
思考一下,傳遞的url爲何是String BASE_URL = "http://beta.goldenalpha.com.cn/"這個格式呢?接着看看baseUrl(httpUrl)源碼
public Builder baseUrl(HttpUrl baseUrl) { checkNotNull(baseUrl, "baseUrl == null"); List<String> pathSegments = baseUrl.pathSegments(); if (!"".equals(pathSegments.get(pathSegments.size() - 1))) { throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl); } this.baseUrl = baseUrl; return this; }
在建立的時候會調用addConverterFactory(GsonConverterFactory.create(JsonUtils.getJson()))添加Gson轉換器
.addConverterFactory(GsonConverterFactory.create(JsonUtils.getGson())) //看這行代碼 public Builder addConverterFactory(Converter.Factory factory) { //將上面建立的GsonConverterFactory放入到 converterFactories數組 converterFactories.add(checkNotNull(factory, "factory == null")); return this; }
而後看看GsonConverterFactory.creat()方法源碼
public static GsonConverterFactory create(Gson gson) { if (gson == null) throw new NullPointerException("gson == null"); return new GsonConverterFactory(gson); }
添加一個調用適配器工廠,用於支持服務方法返回類型
public Builder addCallAdapterFactory(CallAdapter.Factory factory) { callAdapterFactories.add(checkNotNull(factory, "factory == null")); return this; }
CallAdapterFactory:注意Factory生產的是CallAdapter,那麼CallAdapter又是什麼呢?
public interface CallAdapter<R, T> { Type responseType(); T adapt(Call<R> call); abstract class Factory { public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit); protected static Type getParameterUpperBound(int index, ParameterizedType type) { return Utils.getParameterUpperBound(index, type); } protected static Class<?> getRawType(Type type) { return Utils.getRawType(type); } } }
接着,有夥伴可能會問它的做用是什麼呢?
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
用於請求的HTTP客戶端
public Builder client(OkHttpClient client) { return callFactory(checkNotNull(client, "client == null")); } public Builder callFactory(okhttp3.Call.Factory factory) { this.callFactory = checkNotNull(factory, "factory == null"); return this; }
看看源碼
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的構造方法
成功創建一個Retrofit對象的標準:配置好Retrofit類裏的成員變量,即配置好:
Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl, List<Converter.Factory> converterFactories, List<CallAdapter.Factory> callAdapterFactories, @Nullable Executor callbackExecutor, boolean validateEagerly) { this.callFactory = callFactory; this.baseUrl = baseUrl; this.converterFactories = converterFactories; // Copy+unmodifiable at call site. this.callAdapterFactories = callAdapterFactories; // Copy+unmodifiable at call site. this.callbackExecutor = callbackExecutor; this.validateEagerly = validateEagerly; }
而後總結一下建立的過程
大概的流程以下代碼所示
public interface ApiService { @POST("api/v1/user/old") Call<ResEntity<UserOld>> isUserOld(); } //建立接口類實例 ApiService apiService = retrofit.create(ApiService.class); //生成最終的網絡請求對象 Call<ResEntity<UserOld>> userOld = apiService.isUserOld(); //異步機制 userOld.enqueue(new Callback<ResEntity<UserOld>>() { @Override public void onResponse(Call<ResEntity<UserOld>> call, retrofit2.Response<ResEntity<UserOld>> response) { } @Override public void onFailure(Call<ResEntity<UserOld>> call, Throwable t) { } });
源代碼以下所示,這段代碼很重要。
最後建立了網絡請求接口的動態代理對象,經過代理模式中的動態代理模式,動態生成網絡請求接口的代理類,並將代理類的實例建立交給InvocationHandler類 做爲具體的實現,並最終返回一個動態代理對象。
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對象 ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method); //根據配置好的serviceMethod對象建立okHttpCall對象 OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args); //調用OkHttp,並根據okHttpCall返回rejava的Observe對象或者返回Call return serviceMethod.adapt(okHttpCall); } }); }
接着看一下validateServiceInterface方法操做了什麼?
static <T> void validateServiceInterface(Class<T> service) { if (!service.isInterface()) { throw new IllegalArgumentException("API declarations must be interfaces."); } // Prevent API interfaces from extending other interfaces. This not only avoids a bug in // Android (http://b.android.com/58753) but it forces composition of API declarations which is // the recommended pattern. if (service.getInterfaces().length > 0) { throw new IllegalArgumentException("API interfaces must not extend other interfaces."); } }
接着看看eagerlyValidateMethods這個方法的源碼
private void eagerlyValidateMethods(Class<?> service) { Platform platform = Platform.get(); for (Method method : service.getDeclaredMethods()) { if (!platform.isDefaultMethod(method)) { loadServiceMethod(method); } } } 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(); serviceMethodCache.put(method, result); } } return result; }
知道return (T) roxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler invocationHandler)經過代理模式中的動態代理模式,在面試中也常常會問到該模式,那麼該模式有什麼特色呢?
接着看看loadServiceMethod(Method method)方法源碼
建立以前,首先會嘗試根據方法從一個緩存列表中取出ServiceMethod實例,若是沒有,在鎖保護以後,還有再嘗試一次,仍是沒有的狀況下,纔會去建立ServiceMethod。
第一步,先看看ServiceMethod的Builder方法
Builder(Retrofit retrofit, Method method) { this.retrofit = retrofit; this.method = method; this.methodAnnotations = method.getAnnotations(); this.parameterTypes = method.getGenericParameterTypes(); this.parameterAnnotationsArray = method.getParameterAnnotations(); }
第二步,而後看看ServiceMethod的build()方法
public ServiceMethod build() { callAdapter = createCallAdapter(); 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); } 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); }
第三步,看看ServiceMethod(Builder<R, T> builder) 構造方法
ServiceMethod(Builder<R, T> builder) { this.callFactory = builder.retrofit.callFactory(); this.callAdapter = builder.callAdapter; this.baseUrl = builder.retrofit.baseUrl(); this.responseConverter = builder.responseConverter; this.httpMethod = builder.httpMethod; this.relativeUrl = builder.relativeUrl; this.headers = builder.headers; this.contentType = builder.contentType; this.hasBody = builder.hasBody; this.isFormEncoded = builder.isFormEncoded; this.isMultipart = builder.isMultipart; this.parameterHandlers = builder.parameterHandlers; }
首先獲取method的對象表示的方法的形式類型。而後獲取method的註解。重點看看retrofit.callAdapter(returnType, annotations)主要作了什麼?
private CallAdapter<T, R> 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 return (CallAdapter<T, R>) 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); } }
看看retrofit.callAdapter(returnType, annotations)源碼
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) { return nextCallAdapter(null, returnType, annotations); } public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) { checkNotNull(returnType, "returnType == null"); checkNotNull(annotations, "annotations == null"); int start = callAdapterFactories.indexOf(skipPast) + 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; } } StringBuilder builder = new StringBuilder("Could not locate call adapter for ") .append(returnType) .append(".\n"); if (skipPast != null) { builder.append(" Skipped:"); for (int i = 0; i < start; i++) { builder.append("\n * ").append(callAdapterFactories.get(i).getClass().getName()); } builder.append('\n'); } builder.append(" Tried:"); for (int i = start, count = callAdapterFactories.size(); i < count; i++) { builder.append("\n * ").append(callAdapterFactories.get(i).getClass().getName()); } throw new IllegalArgumentException(builder.toString()); }
能夠看到建立OkHttpCall對象須要兩個參數,參數分別是配置好的ServiceMethod對象和輸入的請求參數
final class OkHttpCall<T> implements Call<T> { private final ServiceMethod<T, ?> serviceMethod; private final @Nullable Object[] args; OkHttpCall(ServiceMethod<T, ?> serviceMethod, @Nullable Object[] args) { //含有全部網絡請求參數信息的對象 this.serviceMethod = serviceMethod; //網絡請求接口的參數 this.args = args; } }
接着看看return serviceMethod.adapt(okHttpCall)源碼分析
T adapt(Call<R> call) { return callAdapter.adapt(call); }
接着看看實際的調用
最終建立並返回一個OkHttpCall類型的Call對象或者Observable
ApiService apiService = retrofit.create(ApiService.class); //返回Android默認的Call Call<ResEntity<UserOld>> userOld = apiService.isUserOld(); //返回的則是Observable<T> Observable<AdvertCommon> advert = mApiService.getSplashImage(method)
使用方法Response<Bean> response = call.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()); } //從serviceMethod一個Request對象 private okhttp3.Call createRawCall() throws IOException { okhttp3.Call call = serviceMethod.toCall(args); if (call == null) { throw new NullPointerException("Call.Factory returned null."); } return call; }
如何調用能夠看前面的代碼介紹。這裏就不介紹呢!
@Override public void enqueue(final Callback<T> callback) { checkNotNull(callback, "callback == null"); okhttp3.Call call; Throwable failure; synchronized (this) { if (executed) throw new IllegalStateException("Already executed."); executed = true; call = rawCall; failure = creationFailure; if (call == null && failure == null) { try { call = rawCall = createRawCall(); } catch (Throwable t) { throwIfFatal(t); failure = creationFailure = t; } } } if (failure != null) { callback.onFailure(this, failure); return; } if (canceled) { call.cancel(); } call.enqueue(new okhttp3.Callback() { @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) { Response<T> response; try { response = parseResponse(rawResponse); } catch (Throwable e) { callFailure(e); return; } try { callback.onResponse(OkHttpCall.this, response); } catch (Throwable t) { t.printStackTrace(); } } @Override public void onFailure(okhttp3.Call call, IOException e) { callFailure(e); } private void callFailure(Throwable e) { try { callback.onFailure(OkHttpCall.this, e); } catch (Throwable t) { t.printStackTrace(); } } }); } private okhttp3.Call createRawCall() throws IOException { okhttp3.Call call = serviceMethod.toCall(args); if (call == null) { throw new NullPointerException("Call.Factory returned null."); } return call; }
從上能夠知道,call操做異步,那麼這個call是什麼呢?那麼咱們看一下ExecutorCallAdapterFactory這個類,關於CallAdapterFactory是作什麼用的?前面已經介紹呢!
static final class ExecutorCallbackCall<T> implements Call<T> { final Executor callbackExecutor; final Call<T> delegate; ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) { this.callbackExecutor = callbackExecutor; this.delegate = delegate; } @Override public void enqueue(final Callback<T> callback) { checkNotNull(callback, "callback == null"); 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()) { // 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<T> call, final Throwable t) { callbackExecutor.execute(new Runnable() { @Override public void run() { callback.onFailure(ExecutorCallbackCall.this, t); } }); } }); }
解析網絡數據
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; } }