国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Android網(wǎng)絡(luò)編程11之源碼解析Retrofit

songjz / 1370人閱讀

摘要:此前在例子中調(diào)用的,就是設(shè)置返回的數(shù)據(jù)支持轉(zhuǎn)換為對(duì)象。最終會(huì)返回配置好的類。注釋處遍歷方法來對(duì)請(qǐng)求方式比如和請(qǐng)求地址進(jìn)行解析。的方法主要做的就是用來請(qǐng)求網(wǎng)絡(luò)并將返回的進(jìn)行數(shù)據(jù)轉(zhuǎn)換并回調(diào)給線程。至此,的源碼就講到這里。

前言
最近文章的產(chǎn)出確實(shí)很少,因?yàn)槲艺趯懸槐続ndroid進(jìn)階書籍,兩頭很難兼顧,但是每個(gè)月也得至少發(fā)一篇博客。上一篇我們介紹了Retrofit的使用方法,這一篇我們照例來學(xué)習(xí)Retrofit的源碼。

1.Retrofit的創(chuàng)建過程

當(dāng)我們使用Retrofit請(qǐng)求網(wǎng)絡(luò)時(shí),首先要寫請(qǐng)求接口:

public interface IpService {
    @GET("getIpInfo.php?ip=59.108.54.37")
      Call getIpMsg();

接著我們通過調(diào)用如下代碼來創(chuàng)建Retrofit:

   Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(url)
                .addConverterFactory(GsonConverterFactory.create())
                .build();

Retrofit 是通過建造者模式構(gòu)建出來的,接下來查看Builder方法做了什么:

  public Builder() {
      this(Platform.get());
    }

很簡(jiǎn)短,查看Platform的get方法,如下所示。

 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) {
        return new Android();
      }
    } catch (ClassNotFoundException ignored) {
    }
    try {
      Class.forName("java.util.Optional");
      return new Java8();
    } catch (ClassNotFoundException ignored) {
    }
    try {
      Class.forName("org.robovm.apple.foundation.NSObject");
      return new IOS();
    } catch (ClassNotFoundException ignored) {
    }
    return new Platform();
  }

Platform的get方法最終調(diào)用的是findPlatform方法,根據(jù)不同的運(yùn)行平臺(tái)來提供不同的線程池。接下來查看build方法,代碼如下所示。

   public Retrofit build() {
      if (baseUrl == null) {//1
        throw new IllegalStateException("Base URL required.");
      }
      okhttp3.Call.Factory callFactory = this.callFactory;//2
      if (callFactory == null) {
        callFactory = new OkHttpClient();//3
      }
      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();//4
      }
      List adapterFactories = new ArrayList<>(this.adapterFactories);//5
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
      List converterFactories = new ArrayList<>(this.converterFactories);//6
      return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
          callbackExecutor, validateEagerly);
    }

從注釋1處可以看出baseUrl 是必須指定的。注釋2處callFactory默認(rèn)為this.callFactory,this.callFactory就是我們?cè)跇?gòu)建Retrofit時(shí)調(diào)用callFactory方法所傳進(jìn)來的,如下所示。

   public Builder callFactory(okhttp3.Call.Factory factory) {
      this.callFactory = checkNotNull(factory, "factory == null");
      return this;
    }

因此,如果需要對(duì)OkHttpClient進(jìn)行設(shè)置,則可以構(gòu)建OkHttpClient對(duì)象,然后調(diào)用callFactory方法將設(shè)置好的OkHttpClient傳進(jìn)去。注釋3處,如果沒有設(shè)置callFactory則直接創(chuàng)建OkHttpClient。注釋4的callbackExecutor用來將回調(diào)傳遞到UI線程。注釋5的adapterFactories主要用于存儲(chǔ)對(duì)Call進(jìn)行轉(zhuǎn)化的對(duì)象,后面在Call的創(chuàng)建過程會(huì)再次提到它。注釋6處的converterFactories主要用于存儲(chǔ)轉(zhuǎn)化數(shù)據(jù)對(duì)象,后面也會(huì)提及到。此前在例子中調(diào)用的addConverterFactory(GsonConverterFactory.create()),就是設(shè)置返回的數(shù)據(jù)支持轉(zhuǎn)換為Gson對(duì)象。最終會(huì)返回配置好的Retrofit類。

2.Call的創(chuàng)建過程

緊接著我們創(chuàng)建Retrofit實(shí)例并調(diào)用如下代碼來生成接口的動(dòng)態(tài)代理對(duì)象:

IpService ipService = retrofit.create(IpService.class);

接下來看Retrofit的create方法做了什么,代碼如下所示。

  public  T create(final Class 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, 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 = loadServiceMethod(method);//1
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

可以看到create方法返回了一個(gè)Proxy.newProxyInstance動(dòng)態(tài)代理對(duì)象,當(dāng)我們調(diào)用IpService的getIpMsg方法最終會(huì)調(diào)用InvocationHandler的invoke 方法,它有3個(gè)參數(shù),第一個(gè)是代理對(duì)象,第二個(gè)是調(diào)用的方法,第三個(gè)是方法的參數(shù)。注釋1處的loadServiceMethod(method)中的method就是我們定義的getIpMsg方法。接下來查看loadServiceMethod方法里做了什么:

 private final Map serviceMethodCache = new LinkedHashMap<>();
 ServiceMethod loadServiceMethod(Method method) {
    ServiceMethod result;
    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        result = new ServiceMethod.Builder(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

首先會(huì)從serviceMethodCache查詢傳入的方法是否有緩存,如果有就用緩存的ServiceMethod,如果沒有就創(chuàng)建一個(gè),并加入serviceMethodCache緩存起來。接下來看ServiceMethod是如何構(gòu)建的,代碼如下所示。

   public ServiceMethod build() {
      callAdapter = createCallAdapter();//1
      responseType = callAdapter.responseType();//2
      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();//3
      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);//4
      }
     ...
      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];//5
        if (parameterAnnotations == null) {
          throw parameterError(p, "No Retrofit annotation found.");
        }
        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }
      ...
      return new ServiceMethod<>(this);
    }

注釋1處調(diào)用了createCallAdapter方法,它最終會(huì)得到我們?cè)跇?gòu)建Retrofit調(diào)用build方法時(shí)adapterFactories添加的對(duì)象的get方法,Retrofit的build方法部分代碼:

   List adapterFactories = new ArrayList<>(this.adapterFactories);
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

adapterFactories列表默認(rèn)會(huì)添加defaultCallAdapterFactory,defaultCallAdapterFactory指的是ExecutorCallAdapterFactory,ExecutorCallAdapterFactory的get方法如下所示。

 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;
      }
      @Override public  Call adapt(Call call) {
        return new ExecutorCallbackCall<>(callbackExecutor, call);
      }
    };
  }

get方法會(huì)得到CallAdapter對(duì)象,它的responseType方法會(huì)返回?cái)?shù)據(jù)的真實(shí)類型,比如 Call,它就會(huì)返回IpModel。adapt方法會(huì)創(chuàng)建ExecutorCallbackCall,它會(huì)將call的回調(diào)轉(zhuǎn)發(fā)至UI線程。
接著回到ServiceMethod的 build方法,注釋2處調(diào)用CallAdapter的responseType得到的是返回?cái)?shù)據(jù)的真實(shí)類型。
注釋3處調(diào)用createResponseConverter方法來遍歷converterFactories列表中存儲(chǔ)的Converter.Factory,并返回一個(gè)合適的Converter用來轉(zhuǎn)換對(duì)象。此前我們?cè)跇?gòu)建Retrofit 調(diào)用了addConverterFactory(GsonConverterFactory.create())將GsonConverterFactory(Converter.Factory的子類)添加到converterFactories列表中,表示返回的數(shù)據(jù)支持轉(zhuǎn)換為Json對(duì)象。
注釋4處遍歷parseMethodAnnotation方法來對(duì)請(qǐng)求方式(比如GET、POST)和請(qǐng)求地址進(jìn)行解析。注釋5處對(duì)方法中的參數(shù)注解進(jìn)行解析(比如@Query、@Part)。最后創(chuàng)建ServiceMethod類并返回。
接下來回過頭來查看Retrofit的create方法,在調(diào)用了loadServiceMethod方法后會(huì)創(chuàng)建OkHttpCall,OkHttpCall的構(gòu)造函數(shù)只是進(jìn)行了賦值操作。緊接著調(diào)用serviceMethod.callAdapter.adapt(okHttpCall),callAdapter的adapt方法前面講過,它會(huì)創(chuàng)建ExecutorCallbackCall,ExecutorCallbackCall的部分代碼如下所示。

 ExecutorCallbackCall(Executor callbackExecutor, Call delegate) {
      this.callbackExecutor = callbackExecutor;
      this.delegate = delegate;
    }
    @Override public void enqueue(final Callback callback) {
      if (callback == null) throw new NullPointerException("callback == null");
      delegate.enqueue(new Callback() {//1
        @Override public void onResponse(Call call, final Response response) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              if (delegate.isCanceled()) {
                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);
            }
          });
        }
      });
    }

可以看出ExecutorCallbackCall是對(duì)Call的封裝,它主要添加了通過callbackExecutor將請(qǐng)求回調(diào)到UI線程。
當(dāng)我們得到Call對(duì)象后會(huì)調(diào)用它的enqueue方法,其實(shí)調(diào)用的是ExecutorCallbackCall的enqueue方法,而從注釋1處可以看出ExecutorCallbackCall的enqueue方法最終調(diào)用的是delegate的enqueue方法。delegate從Retrofit的create方法的代碼中我們知道它其實(shí)就是OkHttpCall。

3.Call的enqueue方法

接下來我們就來查看OkHttpCall的enqueue方法,代碼如下所示。

  public void enqueue(final Callback callback) {
    if (callback == null) throw new NullPointerException("callback == null");
    okhttp3.Call call;
   ...
    call.enqueue(new okhttp3.Callback() {//1
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
          throws IOException {
        Response response;
        try {
          response = parseResponse(rawResponse);//2
        } catch (Throwable e) {
          callFailure(e);
          return;
        }
        callSuccess(response);
      }
      ...
  }

注釋1處調(diào)用了okhttp3.Call的enqueue方法。注釋2處調(diào)用parseResponse方法:

  Response parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();
   ...
    int code = rawResponse.code();
    if (code < 200 || code >= 300) {
      try {
        ResponseBody bufferedBody = Utils.buffer(rawBody);
        return Response.error(bufferedBody, rawResponse);
      } finally {
        rawBody.close();
      }
    }
    if (code == 204 || code == 205) {
      return Response.success(null, rawResponse);
    }
    ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
    try {
      T body = serviceMethod.toResponse(catchingBody);//2
      return Response.success(body, rawResponse);
    } catch (RuntimeException e) {
      catchingBody.throwIfCaught();
      throw e;
    }
  }

根據(jù)返回的不同的狀態(tài)碼code值來做不同的操作,如果順利則會(huì)調(diào)用注釋2處的代碼,接下來看toResponse方法里做了什么:

 T toResponse(ResponseBody body) throws IOException {
    return responseConverter.convert(body);
  }

這個(gè)responseConverter就是此前講過在ServiceMethod的build方法調(diào)用createResponseConverter方法返回的Converter,在此前的例子中我們傳入的是GsonConverterFactory,因此可以查看GsonConverterFactory的代碼,如下所示。

public final class GsonConverterFactory extends Converter.Factory {
...
  @Override
  public Converter responseBodyConverter(Type type, Annotation[] annotations,
      Retrofit retrofit) {
    TypeAdapter adapter = gson.getAdapter(TypeToken.get(type));
    return new GsonResponseBodyConverter<>(gson, adapter);
  }
...  
}

在GsonConverterFactory 中有一個(gè)方法responseBodyConverter,它最終會(huì)創(chuàng)建GsonResponseBodyConverter:

final class GsonResponseBodyConverter implements Converter {
  private final Gson gson;
  private final TypeAdapter adapter;
  GsonResponseBodyConverter(Gson gson, TypeAdapter adapter) {
    this.gson = gson;
    this.adapter = adapter;
  }
  @Override public T convert(ResponseBody value) throws IOException {
    JsonReader jsonReader = gson.newJsonReader(value.charStream());
    try {
      return adapter.read(jsonReader);
    } finally {
      value.close();
    }
  }
}

在GsonResponseBodyConverter的convert方法里會(huì)將回調(diào)的數(shù)據(jù)轉(zhuǎn)換為Json格式。因此我們也知道了此前調(diào)用responseConverter.convert是為了轉(zhuǎn)換為特定的數(shù)據(jù)格式。
Call的enqueue方法主要做的就是用OKHttp來請(qǐng)求網(wǎng)絡(luò)并將返回的Response進(jìn)行數(shù)據(jù)轉(zhuǎn)換并回調(diào)給UI線程。
至此,Retrofit的源碼就講到這里。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/70583.html

相關(guān)文章

  • Android開源架構(gòu)

    摘要:音樂團(tuán)隊(duì)分享數(shù)據(jù)綁定運(yùn)行機(jī)制分析一個(gè)項(xiàng)目搞定所有主流架構(gòu)單元測(cè)試一個(gè)項(xiàng)目搞定所有主流架構(gòu)系列的第二個(gè)項(xiàng)目。代碼開源,展示了的用法,以及如何使用進(jìn)行測(cè)試,還有用框架對(duì)的進(jìn)行單元測(cè)試。 Android 常用三方框架的學(xué)習(xí) Android 常用三方框架的學(xué)習(xí) likfe/eventbus3-intellij-plugin AS 最新可用 eventbus3 插件,歡迎品嘗 簡(jiǎn)單的 MVP 模...

    sutaking 評(píng)論0 收藏0
  • Retrofit源碼分析

    摘要:看下圖所示,摘自網(wǎng)絡(luò)的創(chuàng)建流程源碼分析實(shí)例是使用建造者模式通過類進(jìn)行創(chuàng)建的。創(chuàng)建了一個(gè)含有對(duì)象實(shí)例的,并返回給源碼分析添加一個(gè)調(diào)用適配器工廠,用于支持服務(wù)方法返回類型注意生產(chǎn)的是,那么又是什么呢可以看到源代碼如下所示,它是一個(gè)接口。 目錄介紹 1.首先回顧Retrofit簡(jiǎn)單使用方法 2.Retrofit的創(chuàng)建流程源碼分析 2.1 Retrofit對(duì)象調(diào)用Builder()源碼解...

    zero 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

songjz

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<