美文网首页Android笔记
Retrofit2源码试读(一)

Retrofit2源码试读(一)

作者: Young_Allen | 来源:发表于2018-12-14 16:37 被阅读21次

    1.文章介绍

    Retrofit2+Rxjava2+Glide+MVP架构正是火热,以学习角度出发,分模块来熟悉下这种架构的各个模块源码以及实现方式。
    什么情况下使用Retrofit2+Rxjava2呢?Retrofit2+Rxjava2的主要优势是它的解耦性,在项目越复杂时体现出的优势越明显。

    2.干货

    那么就先从Retrofit的使用开始说起,然后再说Rxjava2:

        public static Retrofit getDeafault(String url) {
            Retrofit sRetrofit;
            OkHttpClient.Builder builder = new OkHttpClient.Builder();
            OkHttpClient okHttpClient = builder.build();
            if (BuildConfig.DEBUG) {
                // Log信息拦截器
                HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
                loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
                builder.addInterceptor(loggingInterceptor);
            }
            sRetrofit = new Retrofit.Builder()
                    .baseUrl(url)
                    //设置数据转换工厂类eg:把json数据转换为对象使用GsonConverterFactory
                    .addConverterFactory(GsonConverterFactory.create())
                    //设置数据适配转换工厂类eg:把Callback的接口转化为对RxJava的回调
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .client(okHttpClient)
                    .build();
            return sRetrofit;
        }
    

    以上代码就是关于一个Retrofit简单的初始化。初始化后就可以关联需要请求的数据实现业务处理了:

        public void requesetWeatherInfo() {
    
            Call<DataModel> call = RetrofitUtils.getDeafault(WeatherService.WEATHERSERVICE_URL)
                    .create(WeatherService.class)
                    .loadWeatherInfo("101190201");
    
            call.enqueue(new Callback<DataModel>() {
                @Override
                public void onResponse(Call<DataModel> call, Response<DataModel> response) {
                    DataModel model = response.body();
                    DataModel.WeatherInfoBean bean = model.getWeatherinfo();
                    Log.d(TAG, "onResponse:" + bean.getCity());
                }
    
                @Override
                public void onFailure(Call<DataModel> call, Throwable t) {
                    Log.d(TAG, "onFailure:" + t.getMessage());
                }
            });
        }
    

    这是最基本的Retrofit的使用,为了方便分析先不涉及与Rxjava相关的内容。
    从Retrofit的初始化开始说起,new Retrofit.Builder()使用了建造者模式:

    public static final class Builder {
        private final Platform platform;
        private @Nullable okhttp3.Call.Factory callFactory;
        private @Nullable 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;
    
          // Do not add the default BuiltIntConverters and platform-aware converters added by build().
          for (int i = 1,
              size = retrofit.converterFactories.size() - platform.defaultConverterFactoriesSize();
              i < size; i++) {
            converterFactories.add(retrofit.converterFactories.get(i));
          }
    
          // Do not add the default, platform-aware call adapters added by build().
          for (int i = 0,
              size = retrofit.callAdapterFactories.size() - platform.defaultCallAdapterFactoriesSize();
              i < size; i++) {
            callAdapterFactories.add(retrofit.callAdapterFactories.get(i));
          }
    
          callbackExecutor = retrofit.callbackExecutor;
          validateEagerly = retrofit.validateEagerly;
        }
    
        ...
    
        /**
         * Create the {@link Retrofit} instance using the configured values.
         * <p>
         * Note: If neither {@link #client} nor {@link #callFactory} is called a default {@link
         * OkHttpClient} will be created and used.
         */
        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.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
    
          // Make a defensive copy of the converters.
          List<Converter.Factory> converterFactories = new ArrayList<>(
              1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
    
          // 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);
          converterFactories.addAll(platform.defaultConverterFactories());
    
          return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
              unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
        }
      ...
    }
    

    源码中有converterFactories、callAdapterFactories分别是对数据格式适配和网络请求的适配。最后这些参数都保存在Retrofit这个对象里:

    new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
              unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
    

    另外需要创建业务数据的关联:

     @SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
      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();
              private final Object[] emptyArgs = new Object[0];
    
              @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);
                }
                return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
              }
            });
      }
    

    在这里使用了动态代理模式,这个传入的参数service就是定义的接口类如:

    public interface WeatherService {
        String WEATHERSERVICE_URL = "http://www.weather.com.cn/";
    
        /**
         * 单独使用Retrofit
         * @param cityId
         * @return
         */
        @GET("adat/sk/{cityId}.html")
        Call<DataModel> loadWeatherInfo(@Path("cityId")String cityId);
    }
    

    使用了Java的反射机制创建类的实例:

      @CallerSensitive
        public static Object newProxyInstance(ClassLoader loader,
                                              Class<?>[] interfaces,
                                              InvocationHandler h)
            throws IllegalArgumentException
        {
            Objects.requireNonNull(h);
    
            final Class<?>[] intfs = interfaces.clone();
            // Android-removed: SecurityManager calls
            /*
            final SecurityManager sm = System.getSecurityManager();
            if (sm != null) {
                checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
            }
            */
    
            /*
             * Look up or generate the designated proxy class.
             */
            Class<?> cl = getProxyClass0(loader, intfs);
    
            /*
             * Invoke its constructor with the designated invocation handler.
             */
            try {
                // Android-removed: SecurityManager / permission checks.
                /*
                if (sm != null) {
                    checkNewProxyPermission(Reflection.getCallerClass(), cl);
                }
                */
    
                final Constructor<?> cons = cl.getConstructor(constructorParams);
                final InvocationHandler ih = h;
                if (!Modifier.isPublic(cl.getModifiers())) {
                    // BEGIN Android-changed: Excluded AccessController.doPrivileged call.
                    /*
                    AccessController.doPrivileged(new PrivilegedAction<Void>() {
                        public Void run() {
                            cons.setAccessible(true);
                            return null;
                        }
                    });
                    */
    
                    cons.setAccessible(true);
                    // END Android-removed: Excluded AccessController.doPrivileged call.
                }
                return cons.newInstance(new Object[]{h});
            } catch (IllegalAccessException|InstantiationException e) {
                throw new InternalError(e.toString(), e);
            } catch (InvocationTargetException e) {
                Throwable t = e.getCause();
                if (t instanceof RuntimeException) {
                    throw (RuntimeException) t;
                } else {
                    throw new InternalError(t.toString(), t);
                }
            } catch (NoSuchMethodException e) {
                throw new InternalError(e.toString(), e);
            }
        }
    
       private static Class<?> getProxyClass0(ClassLoader loader,
                                               Class<?>... interfaces) {
            if (interfaces.length > 65535) {
                throw new IllegalArgumentException("interface limit exceeded");
            }
    
            // If the proxy class defined by the given loader implementing
            // the given interfaces exists, this will simply return the cached copy;
            // otherwise, it will create the proxy class via the ProxyClassFactory
            return proxyClassCache.get(loader, interfaces);
        }
    

    重写了InvocationHandler的invoke方法。
    如果是Object类的方法直接通过invoke反射处理:

    if (method.getDeclaringClass() == Object.class) {
      return method.invoke(this, args);
    }
    

    如果是相关平台的基础方法则默认处理:

    if (platform.isDefaultMethod(method)) {
      return platform.invokeDefaultMethod(method, service, proxy, args);
    }
    

    其他情况如开发者自定义的,就通过ServiceMethod处理:

    return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
    
    ServiceMethod<?> loadServiceMethod(Method method) {
        ServiceMethod<?> result = serviceMethodCache.get(method);
        if (result != null) return result;
    
        synchronized (serviceMethodCache) {
          result = serviceMethodCache.get(method);
          if (result == null) {
            result = ServiceMethod.parseAnnotations(this, method);
            serviceMethodCache.put(method, result);
          }
        }
        return result;
      }
    

    需要去解析注解字段,为了优化速度把方法类缓存在serviceMethodCache里

    static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
        RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
        //按本篇文章来分析 这个返回的就是Call<DataModel>
        Type returnType = method.getGenericReturnType();
        if (Utils.hasUnresolvableType(returnType)) {
          throw methodError(method,
              "Method return type must not include a type variable or wildcard: %s", returnType);
        }
        if (returnType == void.class) {
          throw methodError(method, "Service methods cannot return void.");
        }
        return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
      }
    
    final class RequestFactory {
      static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
        return new Builder(retrofit, method).build();
      }
      ...
      Builder(Retrofit retrofit, Method method) {
          this.retrofit = retrofit;
          this.method = method;
          this.methodAnnotations = method.getAnnotations();
          this.parameterTypes = method.getGenericParameterTypes();
          this.parameterAnnotationsArray = method.getParameterAnnotations();
        }
    
        RequestFactory build() {
          for (Annotation annotation : methodAnnotations) {
            parseMethodAnnotation(annotation);
          }
    
          if (httpMethod == null) {
            throw methodError(method, "HTTP method annotation is required (e.g., @GET, @POST, etc.).");
          }
    
          if (!hasBody) {
            if (isMultipart) {
              throw methodError(method,
                  "Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
            }
            if (isFormEncoded) {
              throw methodError(method, "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++) {
            parameterHandlers[p] = parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p]);
          }
    
          if (relativeUrl == null && !gotUrl) {
            throw methodError(method, "Missing either @%s URL or @Url parameter.", httpMethod);
          }
          if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
            throw methodError(method, "Non-body HTTP method cannot contain @Body.");
          }
          if (isFormEncoded && !gotField) {
            throw methodError(method, "Form-encoded method must contain at least one @Field.");
          }
          if (isMultipart && !gotPart) {
            throw methodError(method, "Multipart method must contain at least one @Part.");
          }
    
          return new RequestFactory(this);
        }
        ...
        private void parseMethodAnnotation(Annotation annotation) {
          if (annotation instanceof DELETE) {
            parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
          } else if (annotation instanceof GET) {
            parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
          } else if (annotation instanceof HEAD) {
            parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
          } else if (annotation instanceof PATCH) {
            parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
          } else if (annotation instanceof POST) {
            parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
          } else if (annotation instanceof PUT) {
            parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
          } else if (annotation instanceof OPTIONS) {
            parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
          } else if (annotation instanceof HTTP) {
            HTTP http = (HTTP) annotation;
            parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
          } else if (annotation instanceof retrofit2.http.Headers) {
            String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
            if (headersToParse.length == 0) {
              throw methodError(method, "@Headers annotation is empty.");
            }
            headers = parseHeaders(headersToParse);
          } else if (annotation instanceof Multipart) {
            if (isFormEncoded) {
              throw methodError(method, "Only one encoding annotation is allowed.");
            }
            isMultipart = true;
          } else if (annotation instanceof FormUrlEncoded) {
            if (isMultipart) {
              throw methodError(method, "Only one encoding annotation is allowed.");
            }
            isFormEncoded = true;
          }
        }
        ...
    }
    

    这样就把如下注解的方法解析成一个GET请求,并且请求的地址根据参数cityId转换为"http:***/adat/sk/0124.html"等地址:

    @GET("adat/sk/{cityId}.html")
    Call<DataModel> loadWeatherInfo(@Path("cityId")String cityId);
    

    那么这个返回值Call的泛型是在哪处理,答案是在解析完Annotations后:

      static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
          Retrofit retrofit, Method method, RequestFactory requestFactory) {
        // 根据本文的分析,这里使用的CallAdapter是ExecutorCallAdapterFactory
        CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
        // 这里是泛型的实际类型,本文这里是DataModel
        Type responseType = callAdapter.responseType();
        if (responseType == Response.class || responseType == okhttp3.Response.class) {
          throw methodError(method, "'"
              + Utils.getRawType(responseType).getName()
              + "' is not a valid response body type. Did you mean ResponseBody?");
        }
        if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
          throw methodError(method, "HEAD method must use Void as response type.");
        }
    
        Converter<ResponseBody, ResponseT> responseConverter =
            createResponseConverter(retrofit, method, responseType);
    
        okhttp3.Call.Factory callFactory = retrofit.callFactory;
        return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
      }
    
      private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
          Retrofit retrofit, Method method) {
        // 这里的retrunType就是方法的返回值 即Call<DataModel>
        Type returnType = method.getGenericReturnType();
        Annotation[] annotations = method.getAnnotations();
        try {
          //noinspection unchecked
          return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
        } catch (RuntimeException e) { // Wide exception range because factories are user code.
          throw methodError(method, e, "Unable to create call adapter for %s", returnType);
        }
      }
    

    注意returnType很重要,之后有多处需要用到。
    这一步就要开始涉及到CallAdapter,还记得在初始化的时候会有一个callAdapterFactories的列表吧,在这个时候就要派上用场了:

      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());
      }
    

    当我们没有addCallAdapterFactory时,Retrofit是如何处理的呢?

      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.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
    

    这里要注意参数callbackExecutor是Android的MainThreadExecutor:

    static class Android extends Platform {
        @IgnoreJRERequirement // Guarded by API check.
        @Override boolean isDefaultMethod(Method method) {
          if (Build.VERSION.SDK_INT < 24) {
            return false;
          }
          return method.isDefault();
        }
    
        @Override public Executor defaultCallbackExecutor() {
          return new MainThreadExecutor();
        }
    
        static class MainThreadExecutor implements Executor {
          private final Handler handler = new Handler(Looper.getMainLooper());
    
          @Override public void execute(Runnable r) {
            handler.post(r);
          }
        }
        ...
    }
    
      List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
          @Nullable Executor callbackExecutor) {
        if (callbackExecutor != null) {
          return singletonList(new ExecutorCallAdapterFactory(callbackExecutor));
        }
        return singletonList(DefaultCallAdapterFactory.INSTANCE);
      }
    

    除了添加用户定义的callAdapter外,会默认添加defaultCallAdapter或者ExecutorCallAdapterFactory。
    由于简书的字数限制,把分析放在了Retrofit2源码试读(二)中 。

    3.结束语

    比较简陋的把Retrofit的源码摸了一遍,了解了其中部分实现机制,发现确实解耦的比较好,目前只是初试Retrofit源码,有个框架上的认识而已,通过积累会完善这个系列。
    Rxjava的分析会是下一步的计划,反正都是难啃的骨头,一起加油!文章的分析流程不确保完全正确,有分析的不对的地方欢迎指正。

    相关文章

      网友评论

        本文标题:Retrofit2源码试读(一)

        本文链接:https://www.haomeiwen.com/subject/wnruhqtx.html