<strike id="cy2gs"><menu id="cy2gs"></menu></strike>
  • <del id="cy2gs"><dfn id="cy2gs"></dfn></del>
  • 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.skdbbs.com )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 平面設計服務

    日歷

    鏈接

    個人資料

    藍藍設計的小編 http://www.skdbbs.com

    存檔

    主站蜘蛛池模板: 无码人妻精品中文字幕免费| 久久r热这里有精品视频| 2048亚洲精品国产| 国产欧美精品区一区二区三区| 91精品国产乱码久久久久久| 欧美ppypp精品一区二区| 亚洲国产精品久久久久久| 久久久久久久亚洲精品| 亚洲国产精品成人久久| 国产精品日韩深夜福利久久| 亚洲精品老司机在线观看| 亚洲国语精品自产拍在线观看| 三级高清精品国产| 国产精品自产拍在线观看花钱看| 亚洲av永久无码精品网站| 欧美精品一二区| 国产精品亚洲精品日韩已方 | 欧美成人精品高清在线观看| 欧美精品一区二区三区免费| 国内精品久久久久久久久| 国产A√精品区二区三区四区| 亚洲国产精品无码AAA片| 亚洲国产精品成人一区| 精品视频一区二区三区在线观看| 久久中文精品无码中文字幕| 国产成人精品视频在放| 精品免费久久久久久久| 亚洲麻豆精品国偷自产在线91| 久草视频在线这里精品| 国产成人久久精品一区二区三区 | 四虎国产精品永久地址入口| 久久精品女人天堂AV麻| 国产在线精品一区二区高清不卡| 久久99精品久久久久久久不卡 | 久久国产精品久久国产精品| 成人区人妻精品一区二区不卡视频| 久久国产精品免费一区| 国产亚洲精品看片在线观看| 国产精品综合专区中文字幕免费播放 | 无码精品第一页| 蜜臀AV无码国产精品色午夜麻豆 |