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

資訊專欄INFORMATION COLUMN

RTFSC系列之Retrofit

lpjustdoit / 3265人閱讀

摘要:從開始,的底層實現已替換成了,也因此成為了平臺上主流的網絡框架之一。,負責把接口方法注解轉換為表示包括等,負責把轉換為,并且包裝了的接口調用。負責把轉為,使其具備線程調度能力。其內部接口負責把請求響應結果轉換可識別的數據格式。

Retrofit基本介紹
Retrofit是Square開源的一個適用于Android和Java的類型安全的HTTP網絡框架。其本質是對OKHttp的進一步封裝,通過接口的方式進行網絡請求,結合了注解、動態代理等技術實現模塊解耦,簡化了網絡請求的上層邏輯。從Android4.4開始,http的底層實現已替換成了OKHttp,Retrofit也因此成為了Android平臺上主流的網絡框架之一。

http://square.github.io/retro...

Retrofit使用方法

Step1:聲明Retrofit API請求接口

    public interface GitHub {
        @GET("/repos/{owner}/{repo}/contributors")
        Call> contributors(
            @Path("owner") String owner,
            @Path("repo") String repo);
    }

請求類型:以@GET/POST/PUT/DELETE注解聲明

請求相對URL:以請求方法注解內的Value值表示

請求參數:以接口方法@Path參數表示

Step2:構建Retrofit對象并創建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);

通過baseUrl接口聲明接口請求域名;

配置對象的序列化和反序列化轉換工廠;

Step3:通過API接口方法創建Call實例并發起請求

    // Create a call instance for looking up Retrofit contributors.
    Call> call = github.contributors("square", "retrofit");

    // Fetch and print a list of the contributors to the library.
    List contributors = call.execute().body();

Retrofit的實現就是這么簡單優雅,業務層只需要像調用普通接口一樣即可完成網絡請求。

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 callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

      // Make a defensive copy of the converters.
      List 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);
    }
  }

callFactory,生產并處理請求的工廠(默認創建OKHttpClient)

callbackExecutor,用以處理callback線程調度(Android默認回調到主線程)

callAdapterFactories,用以生產CallAdapter以處理Response類型轉換(默認使用ExecutorCallAdapterFactory)

converterFactories,用以生產Converter處理http請求響應的數據轉換(默認使用BuiltInConverters)

Retrofit實例化完成,創建API接口動態代理實現。

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, @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.adapt(okHttpCall);
          }
        });
  }


serviceMethod,負責把接口方法注解轉換為http表示(包括httpMethod/header/body/url等)

okHttpCall,負責把serviceMethod轉換為okhttp3.Call,并且包裝了okhttp3.Call的接口調用。

serviceMethod.adapt:負責把OKHttpCall轉為ExecutorCallbackCall,使其具備線程調度能力。

接口動態代理創建完成,開始執行網絡請求。

OKHttpCall.execute

    @Override 
    public Response 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,后者主要負責:

把接口注解參數轉換為okhttp3.Call原始請求

執行okhttp3.Call接口請求,獲取Response結果

把ResponseBody轉換為接口返回數據類型并回調

1. ServiceMethod.toCall負責將注解參數轉換為okhttp3.Call

/** 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[] handlers = (ParameterHandler[]) 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解析及請求結果狀態的封裝回調。

Response 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請求響應結果轉換可識別的數據格式。舉個栗子:*

VoidResponseBodyConverter:不做處理,直接返回RequestBody

GsonResponseBodyConverter:將字節流轉換為Java對象

ToStringConverter:將RequestBody轉換為String

/** 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 contributors = call.execute().body();

到此,一個Retrofit GET同步請求流程基本分析完了。想要加深理解,Read the fucking source code!

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/69339.html

相關文章

  • Android網絡編程9Retrofit2前篇[基本使用]

    摘要:創建增加返回值為的支持這里的加上之前定義的參數形成完整的請求地址用于指定返回的參數數據類型,這里我們支持和類型。完整的代碼如下增加返回值為的支持請求參數上文講了訪問網絡的基本方法,接下來我們來了解下常用的請求參數。 前言 Retrofit是Square公司開發的一款針對Android網絡請求的框架,Retrofit2底層基于OkHttp實現的,而OkHttp現在已經得到Google官方...

    Nosee 評論0 收藏0
  • Java進階

    摘要:探索專為而設計的將探討進行了何種改進,以及這些改進背后的原因。關于最友好的文章進階前言之前就寫過一篇關于最友好的文章反響很不錯,由于那篇文章的定位就是簡單友好,因此盡可能的摒棄復雜的概念,只抓住關鍵的東西來講,以保證大家都能看懂。 周月切換日歷 一個可以進行周月切換的日歷,左右滑動的切換月份,上下滑動可以進行周,月不同的視圖切換,可以進行事件的標記,以及節假日的顯示,功能豐富 Andr...

    sushi 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<