<address id="ttjl9"></address>

      <noframes id="ttjl9"><address id="ttjl9"><nobr id="ttjl9"></nobr></address>
      <form id="ttjl9"></form>
        <em id="ttjl9"><span id="ttjl9"></span></em>
        <address id="ttjl9"></address>

          <noframes id="ttjl9"><form id="ttjl9"></form>

          Retrofit源碼分析

          2018-9-3    seo達人

          如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里

          1、簡介

          retrofit是一個封裝okhttp請求的網絡請求庫,可以通過Rxjava適配返回信息。

          2、原理分析

          我們通過Retrofit.Builder建造者模式創建一個Retrofit實例對象

          public static final class Builder {
              /**
                *Android線程切換的類 
                */
              private final Platform platform;
              private @Nullable okhttp3.Call.Factory callFactory;
              private HttpUrl baseUrl;
              private final List<Converter.Factory> converterFactories = new ArrayList<>();
              private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
              private @Nullable Executor callbackExecutor;
              private boolean validateEagerly;
          
              Builder(Platform platform) {
                this.platform = platform;
              }
          
              public Builder() {
                this(Platform.get());
              }
          
              Builder(Retrofit retrofit) {
                platform = Platform.get();
                callFactory = retrofit.callFactory;
                baseUrl = retrofit.baseUrl;
          
                converterFactories.addAll(retrofit.converterFactories);
                // Remove the default BuiltInConverters instance added by build().
                converterFactories.remove(0);
          
                callAdapterFactories.addAll(retrofit.callAdapterFactories);
                // Remove the default, platform-aware call adapter added by build().
                callAdapterFactories.remove(callAdapterFactories.size() - 1);
          
                callbackExecutor = retrofit.callbackExecutor;
                validateEagerly = retrofit.validateEagerly;
              }
          
              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 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);
              }
          
              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;
              }
          
              public Builder addConverterFactory(Converter.Factory factory) {
                converterFactories.add(checkNotNull(factory, "factory == null"));
                return this;
              }
          
              public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
                callAdapterFactories.add(checkNotNull(factory, "factory == null"));
                return this;
              }
          
              public Builder callbackExecutor(Executor executor) {
                this.callbackExecutor = checkNotNull(executor, "executor == null");
                return this;
              }
          
              public List<CallAdapter.Factory> callAdapterFactories() {
                return this.callAdapterFactories;
              }
          
              public List<Converter.Factory> converterFactories() {
                return this.converterFactories;
              }
          
              public Builder validateEagerly(boolean validateEagerly) {
                this.validateEagerly = validateEagerly;
                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);
              }
           } 
              
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31
          • 32
          • 33
          • 34
          • 35
          • 36
          • 37
          • 38
          • 39
          • 40
          • 41
          • 42
          • 43
          • 44
          • 45
          • 46
          • 47
          • 48
          • 49
          • 50
          • 51
          • 52
          • 53
          • 54
          • 55
          • 56
          • 57
          • 58
          • 59
          • 60
          • 61
          • 62
          • 63
          • 64
          • 65
          • 66
          • 67
          • 68
          • 69
          • 70
          • 71
          • 72
          • 73
          • 74
          • 75
          • 76
          • 77
          • 78
          • 79
          • 80
          • 81
          • 82
          • 83
          • 84
          • 85
          • 86
          • 87
          • 88
          • 89
          • 90
          • 91
          • 92
          • 93
          • 94
          • 95
          • 96
          • 97
          • 98
          • 99
          • 100
          • 101
          • 102
          • 103
          • 104
          • 105
          • 106
          • 107
          • 108
          • 109
          • 110
          • 111
          • 112
          • 113
          • 114
          • 115
          • 116
          • 117
          • 118
          • 119
          • 120
          • 121
          • 122
          • 123
          • 124
          • 125
          • 126
          • 127
          • 128
          • 129

          通過Retrofit.Builder中build方法創建一個Retrofit實例對象,在創建Retrofit時會判斷用戶創建OkhttpClient對象,沒有創建Retrofit會創建一個默認okhttpClient對象,然后設置Platform中的主線程線程池,設置線程池處理器交給主線程Looper對象。然后創建一個Retrofit對象。我們通過Retrofit.create創建一個接口代理類

           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);
                    }
                  });
            } 
              
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26

          在調用Creater方法時,通過代理類創建Service實例對象,當我們通過接口實例對象調用方法時,通過invoke方法時,通過Method創建一個ServiceMethod對象,然后把ServiceMethod存儲起來

           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);
                  }
          
              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);
                    }
                  } 
              
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31
          • 32
          • 33
          • 34
          • 35
          • 36
          • 37
          • 38
          • 39
          • 40
          • 41
          • 42
          • 43
          • 44
          • 45
          • 46
          • 47
          • 48
          • 49
          • 50
          • 51
          • 52
          • 53
          • 54
          • 55
          • 56
          • 57
          • 58
          • 59
          • 60
          • 61
          • 62
          • 63
          • 64
          • 65
          • 66
          • 67
          • 68
          • 69
          • 70
          • 71
          • 72
          • 73
          • 74
          • 75
          • 76
          • 77
          • 78
          • 79
          • 80
          • 81
          • 82
          • 83
          • 84
          • 85

          在創建ServiceMethod時,獲取我們okhttp請求是否有返回值,沒有返回值拋出異常,然后獲取注解信息,然后獲取retrofit中CallAdapter.Factory,然后調用get方法,我們在通過rxjavaFactoryAdapter.create創建的就是實現CallAdapter.Factory對象,然后調用CallAdapter.Factory中respenseType方法,然后通過我們傳遞converter對數據進行序列化,可以通過gson和fastjson進行實例化對象,然后通過parseMethodAnnomation解析請求類型

           private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
                    if (this.httpMethod != null) {
                      throw methodError("Only one HTTP method is allowed. Found: %s and %s.",
                          this.httpMethod, httpMethod);
                    }
                    this.httpMethod = httpMethod;
                    this.hasBody = hasBody;
          
                    if (value.isEmpty()) {
                      return;
                    }
          
                    // Get the relative URL path and existing query string, if present.
                    int question = value.indexOf('?');
                    if (question != -1 && question < value.length() - 1) {
                      // Ensure the query string does not have any named parameters.
                      String queryParams = value.substring(question + 1);
                      Matcher queryParamMatcher = PARAM_URL_REGEX.matcher(queryParams);
                      if (queryParamMatcher.find()) {
                        throw methodError("URL query string \"%s\" must not have replace block. "
                            + "For dynamic query parameters use @Query.", queryParams);
                      }
                    }
          
                    this.relativeUrl = value;
                    this.relativeUrlParamNames = parsePathParameters(value);
                  } 
              
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28

          通過注解類型獲取到請求類型時,通過調用相關方法解析獲取到請求url,然后通過注解獲取方法中是否有注解字段,有注解信息存儲到Set集合中。然后創建一個OkhttpCall對象,通過調用serviceMethod.adapt方法做網絡請求,serviceMethod.adapt調用是callAdapter中的adapt方法,如果用戶沒有設置callAdapter模式使用的是ExecutorCallAdapterFactory中的adapt方法

           public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
                      if (getRawType(returnType) != Call.class) {
                          return null;
                      } else {
                          final Type responseType = Utils.getCallResponseType(returnType);
                          return new CallAdapter<Object, Call<?>>() {
                              public Type responseType() {
                                  return responseType;
                              }
          
                              public Call<Object> adapt(Call<Object> call) {
                                  return new ExecutorCallAdapterFactory.ExecutorCallbackCall(ExecutorCallAdapterFactory.this.callbackExecutor, call);
                              }
                          };
                      }
                  } 
              
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17

          在ExectorCallAdapterFactory中調用組裝的Call方法中enqueue方法調用異步網絡請求,成功后通過Platform中MainThreadExecutor切換到主線程。在調用callback中的enqueue,onResponse和onFairlure方法時實際是調用到OkhttpCall方法的onResponse方法,在OkHttpCall.enqueue中重新組建OkHttp.Call url和參數信息,然后封裝請求,請求成功后通過parseResponse解析返回信息狀態,然后把返回信息狀態成ResponseBody對象,調用ServiceMethod.toResponse解析,在toResponse中實際是我們設置ConverterFactory對象解析數據,完成后調用callBack中onSuccess方法。

           @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();
                      }
                    }
                  });
                }
          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務

          日歷

          鏈接

          個人資料

          藍藍設計的小編 http://www.syprn.cn

          存檔

          亚洲va欧美va天堂v国产综合