美文网首页js css html
读懂 Retrofit 原理~

读懂 Retrofit 原理~

作者: Drew_MyINTYRE | 来源:发表于2022-07-20 17:15 被阅读0次

    什么是 REST ful API?

    一句话概括 REST ful API:在我们使用 HTTP 协议做数据传输时应当遵守 HTTP 的规矩,包括请求方法、资源类型、Uri 格式等等..

    为什么将请求设置为(接口+注解)形式?

    迪米特法则:也称之为最小知道原则,即模块之间尽量减少不必要的依赖,即降低模块间的耦合性。

    门面模式:基于迪米特法则拓展出来的一种设计模式,旨在将复杂的模块/系统访问入口控制的更加单一。举个例子:现要做一个获取图片功能,优先从本地缓存获取,没有缓存从网络获取随后再加入到本地缓存,假如不做任何处理,那每获取一张图片都要写一遍缓存逻辑,写的越多出错的可能就越高,其实调用者只是想获取一张图片而已,具体如何获取他不需要关心。此时可以通过门面模式将缓存功能做一个封装,只暴露出一个获取图片入口,这样调用者使用起来更加方便而且安全性更高。其实函数式编程也是门面模式的产物。

    为什么通过门面模式设计 ApiService

    Retrofit 做一次请求大致流程如下:

    interface ApiService {
        /**
         * 获取首页数据
         */
        @GET("/article/list/{page}/json")
        suspend fun getHomeList(@Path("page") pageNo: Int)
        : ApiResponse<ArticleBean>
    }
    
    //构建Retrofit
    val retrofit = Retrofit.Builder().build()
    
    //创建ApiService实例
    val apiService =retrofit.create(ApiService::class.java)
    
    //发起请求(这里用的是suspend会自动发起请求,Java中可通过返回的call请求)
    apiService.getHomeList(1)
    

    我们都知道 Retrofit 只不过是对 OkHttp 做了封装。如果直接使用 OkHttp,当在构造 Request 时要做很多繁琐的工作,最要命的是 Request 可能在多处被构造(ViewModel、Repository...),写的越分散出错时排查的难度就越高。而 Retrofit 通过注解的形式将 Request 需要的必要信息全依附在方法上(还是个抽象方法,尽量撇除一切多余信息),作为使用者只需要调用对应方法即可实现请求。至于如何解析、构造、发起请求 Retrofit 内部会做处理,调用者不想也不需要知道,所以 Retrofit 通过门面模式帮调用者屏蔽了一些无用信息,只暴露出唯一入口,让调用者更专注于业务开发。像我们常用的 Room、GreenDao 也使用了这种模式。

    动态代理其实不是工具

    Retrofit 构建如下所示:

    Retrofit.Builder()
        .client(okHttpClient)
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
        .baseUrl(ApiConstants.BASE_URL)
        .build()
    

    很典型的构建者模式,可以配置 OkHttpGsonRxJava 等等,最后通过build() 做构建操作,跟一下 build() 代码:

    # Retrofit.class
    
    public Retrofit build() {
    
            // 1. CallAdapter 工厂集合
            List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
            callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
    
            // 2. Converter 工厂集合
            List<Converter.Factory> converterFactories =
                    new ArrayList<>(
                            1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
            converterFactories.add(new BuiltInConverters());
            converterFactories.addAll(this.converterFactories);
            converterFactories.addAll(platform.defaultConverterFactories());
    
            return new Retrofit(
                  callFactory,
                    baseUrl,
                    unmodifiableList(converterFactories),
                    unmodifiableList(callAdapterFactories),
                    callbackExecutor,
                    validateEagerly);
        }
    

    什么是动态代理?

    动态代理是可以在运行期动态创建某个 interface 的实例,我们通过 Proxy.newProxyInstance 产生的代理类,当调用接口的任何方法时,都会被InvocationHandler#invoke 方法拦截,同时,在这个方法中可以拿到所传入的参数等,依照参数值再做相应的处理。

    每次 CRUD 都会手动做一次上报操作,这显然是模版代码,如何解决?下面来看动态代理:

    interface ToDo {
        fun buyHouse()
    }
    
    /**
     * 中介
     */
    class Middlemen(private val any: Any) : InvocationHandler {
        override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any? {
            return method?.invoke(any, *(args ?: arrayOfNulls<Any>(0)))
        }
    }
    
    /**
     * 买家
     */
    class Buyer : ToDo {
        override fun buyHouse() {
            print("中介,请帮我买房子")
        }
    }
    
    // 最后利用代理对象实现购房的动作:
    fun main(args: Array<String>) {
            val toDo: ToDo = Buyer()
            val dynamicMid = Proxy.newProxyInstance(
                toDo.javaClass.classLoader, toDo.javaClass.interfaces,
                Middlemen(toDo)
            ) as ToDo
            dynamicMid.buyHouse()
        }
    

    动态代理最主要的部分在于代理对象实现 InvocationHandler,并重写 invoke 方法。 当代理对象代理了委托者的要求,不管要求有多少,当代理执行时,都会走进 invoke() 方法中。这是重点,圈起来后面要考。

    动态代理获取 ApiService

    # Retrofit.class
    
      public <T> T create(final Class<T> service) {
        validateServiceInterface(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 @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args)
                      throws Throwable {
                    // ⚠️
                    if (method.getDeclaringClass() == Object.class) {
                      return method.invoke(this, args);
                    }
                    args = args != null ? args : emptyArgs;
                    
                    // ⚠️
                    return platform.isDefaultMethod(method)
                        ? platform.invokeDefaultMethod(method, service, proxy, args)
                        : loadServiceMethod(method).invoke(args);
                  }
                });
      }
    

    invoke() 这是一个代理方法,调用 ApiService中的任一方法并执行,其中参数 methodargs 代表 ApiService 对应的方法和参数。返回值中有一个isDefaultMethod,这里如果是 Java8 的默认方法直接执行,毕竟我们只需要代理 ApiService 中方法即可。经过反复筛选最后重任落在了loadServiceMethod,这也是 Retrofit 中最核心的一个方法,下面我们来跟一下:

    loadServiceMethod(method) 它主要是将网络请求方法中的信息进行初步的处理,我们在创建 api service 具体接口时,会加上注解( @GET@POST@PUT...),参数( @Path@Query ... )等,该方法就是对接口中的注解、参数等进行解析,解析接口后又生成了一个 RequestFactory 请求工厂对象,并且利用这个 RequestFactory 对象创建了一个 CallAdapter

    CallAdapter: 适配器,我们默认定义 API Service 方法的返回值为 Call 类型,但是有时候会自定义返回类型,例如和 RxJava 相结合,返回Observable 或者 Single 类型的时候应该怎么处理?CallAdapter 的作用就是帮助开发者去适配这些返回类型,你定义了什么类型的数据,就可以通过CallAdapter#adapt 进行返回。

    # Retrofit.class
    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;
      }
    

    创建 ServiceMethod 对象是通过其静态方法 parseAnnotations 实现的,再跟一下这个方法:

    # HttpServiceMethod.class
    
    static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
                Retrofit retrofit, Method method, RequestFactory requestFactory) {
            boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
            boolean continuationWantsResponse = false;
            boolean continuationBodyNullable = false;
    
            Annotation[] annotations = method.getAnnotations();
            Type adapterType;
            //1.获取adapterType,默认为method返回值类型
            if (isKotlinSuspendFunction) {
                Type[] parameterTypes = method.getGenericParameterTypes();
                Type responseType =
                        Utils.getParameterLowerBound(
                                0, (ParameterizedType) parameterTypes[parameterTypes.length - 1]);
                if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
                    // Unwrap the actual body type from Response<T>.
                    responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
                    continuationWantsResponse = true;
                } else {
                }
                adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
                annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
            } else {
                adapterType = method.getGenericReturnType();
            }
            //2.创建CallAdapter
            CallAdapter<ResponseT, ReturnT> callAdapter =
                    createCallAdapter(retrofit, method, adapterType, annotations);
            Type responseType = callAdapter.responseType();
            //3.创建responseConverter
            Converter<ResponseBody, ResponseT> responseConverter =
                    createResponseConverter(retrofit, method, responseType);
    
            okhttp3.Call.Factory callFactory = retrofit.callFactory;
            //4.创建HttpServiceMethod类型具体实例
            if (!isKotlinSuspendFunction) {
                return new HttpServiceMethod.CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
            }
            //兼容kotlin suspend方法
            else if (continuationWantsResponse) {
                //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
                return (HttpServiceMethod<ResponseT, ReturnT>)
                        new HttpServiceMethod.SuspendForResponse<>(
                                requestFactory,
                                callFactory,
                                responseConverter,
                                (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
            } else {
                //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
                return (HttpServiceMethod<ResponseT, ReturnT>)
                        new HttpServiceMethod.SuspendForBody<>(
                                requestFactory,
                                callFactory,
                                responseConverter,
                                (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
                                continuationBodyNullable);
            }
        }
    
    # ServiceMethod.class
     static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
            // ⚠️
            RequestFactory requestFactory =
                RequestFactory.parseAnnotations(retrofit, method);
            Type returnType = method.getGenericReturnType();
            ...
            // ⚠️
            return HttpServiceMethod.parseAnnotations(retrofit,
                    method, requestFactory);
        }
    
    # HttpServiceMethod.class
    @Override
      final @Nullable ReturnT invoke(Object[] args) {
        Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
        return adapt(call, args);
      }
    

    OkHttpCall 其实是对 OkHttp 中的 realCall 进行了一层包装,realCall 是如何创建的?

    先创建 OkHttpClientRequest 对象,以 Request 来创建一个 RealCall 对象,利用它执行异步 enqueue 或者同步 execute 操作将请求发送出去,并监听请求失败或者成功的反馈 Callback

    val okHttpClient = OkHttpClient()
    val request: Request = Request.Builder()
        .url("https://cn.bing.com/")
        .build()
    
    okHttpClient.newCall(request).enqueue(object : Callback{
        override fun onFailure(call: Call, e: IOException) {
        }
    
        override fun onResponse(call: Call, response: Response) {
        }
    })
    

    这里有三个主要的类需要说明一下:OkHttpClientRequest 以及 RealCall

    • OkHttpClient: 相当于配置中⼼,可用于发送 HTTP 请求并读取其响应。它的配置有很多,例如 connectTimeout:建⽴连接(TCP 或 TLS)的超时时间,readTimeout :发起请求到读到响应数据的超时时间,Dispatcher:调度器,⽤于调度后台发起的⽹络请求,等等。还有其他配置可查看源码。

    • Request: 一个主要设置网络请求 Url、请求方法(GET、POST......)、请求头、请求 body 的请求类。

    • RealCallRealCall 是由 newCall(Request) 方法返回,是 OkHttp 执行请求最核心的一个类之一,用作连接 OkHttp 的应用程序层和网络层,也就是将 OkHttpClientRequest 结合起来,发起异步和同步请求。

    loadServiceMethod(method).invoke(args);, loadServiceMethod(method) 返回的是 HttpServiceMethod, invoke() 创建了一个 OkHttpCall 实例,它内部其实就是对 OkHttp 的一系列操作。

    我们再来看看 OkHttpCall 中网络请求的细节:

      @Override
      public void enqueue(final Callback<T> callback) {
        Objects.requireNonNull(callback, "callback == null");
    
        okhttp3.Call call;
        synchronized (this) {
          ...
          if (call == null && failure == null) {
            try {
              call = rawCall = createRawCall();
            }
          }
        ...
        call.enqueue(
            new okhttp3.Callback() {
              @Override
              public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
                Response<T> response;
                try {
                  //解析请求返回值
                  response = parseResponse(rawResponse);
                }
                  ...
                try {
                  callback.onResponse(OkHttpCall.this, response);
                }
    
              @Override
              public void onFailure(okhttp3.Call call, IOException e) {
                callFailure(e);
              }
    
              private void callFailure(Throwable e) {
                try {
                  callback.onFailure(OkHttpCall.this, e);
                }
              }
            });
      }
    

    分析上面的源码:

    1,内部首先调用了一个 createRawCall() 方法,创建 rawCall,这个 rawCall 其实指代的就是 Okhttp3 的 call,也就是 OkHttp 进行网络请求调用的一个调度器;

    2,创建好 OkHttp 的 call 后,就开始调用 enqueue 进行异步请求,发现在异步请求内响应的回调属于 okhttp3.Callback,所返回来的结果,也都是 okhttp3.Response,到这里就可以大概知道了,retrofit 的网络请求其实还是由 OkHttp 来实现。

    3,okhttp3.Response 这个响应不方便开发者直接使用,所以 retrofit 在收到结果后,又对响应结果进行新一轮的解析 response = parseResponse(rawResponse),以 Response 对象的形式返回给开发者。

    另外还有最后一行: adapt(call, args) ; 它的内部其实是由一个适配器CallAdapted 来调用,如下:

      protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
          return callAdapter.adapt(call);
        }
    

    adapt 是一个抽象方法,里面传入了上面刚创建的 OkHttpCall 作为参数。adapt 即 adapter,适配器的意思,那我们可以猜测一下,传入 OkHttpCall,是不是就是为了对 OkHttpCall 再进行适配的工作?但,OkHttpCall 已经可以进行网络请求了,为什么还需要使用 CallAdapted 进行再次的适配呢? ⁉️这个问题还是先记下,抛到后面解答。

    从上面分析知道,Retrofit 之所以调用简便,是因为内部对 @GET@POST@Path 等注解以及请求参数进行了解析,让开发者只需要关心自己新增的请求方法是不是符合规范。而上述动态代理最主要做的事情就是创建了 CallAdaptedCallAdapted 其实只是一个适配器,主要需要了解的是它适配的是什么? 是否还记得我们在上面抛出了一个关于 CallAdapted 的问题:那就先来看看他是如何创建的?⁉️

    abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
    
      static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
          Retrofit retrofit, Method method, RequestFactory requestFactory) {
    
        Type adapterType;
        if (isKotlinSuspendFunction) {
          Type[] parameterTypes = method.getGenericParameterTypes();
          Type responseType =
              Utils.getParameterLowerBound(
                  0, (ParameterizedType) parameterTypes[parameterTypes.length - 1]);
          if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
            // Unwrap the actual body type from Response<T>.
            responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
            continuationWantsResponse = true;
          }
    
          adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
          annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
        } else {
          adapterType = method.getGenericReturnType();
        }
    
        CallAdapter<ResponseT, ReturnT> callAdapter =
            createCallAdapter(retrofit, method, adapterType, annotations);
      ...
    
        Converter<ResponseBody, ResponseT> responseConverter =
            createResponseConverter(retrofit, method, responseType);
    
        okhttp3.Call.Factory callFactory = retrofit.callFactory;
        if (!isKotlinSuspendFunction) {
          return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
        }
    
    public CallAdapter<?, ?> nextCallAdapter(
          @Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) {
        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;
          }
        }
    

    CallAdapter 是根据 returnTypeannotations 的类型,从 callAdapterFactories 工厂中进行查找,从而返回所对应的网络请求适配器,这里 returnType 指的是网络请求接口里方法的返回值类型,如 CallObservable 等。annotations 则指代的是注解类型,如 @GET@POST 等。

    这里也提到了一个适配器工厂 callAdapterFactories,不同的 CallAdapter 就是从这个工厂中查询出来的,有查找那就必定有添加,那适配器 CallAdapter 是怎么添加到工厂类中的? ⁉️callAdapterFactories 这个变量是属于 Retrofit 类,跟踪发现是由 Retrofit 构造函数传入,也就是 Retrofit 初始化时进行了赋值。

    Retrofit 的初始化是由一种建造者模式来创建,在 Retrofitbuild() 方法中,找到了适配器工厂对其适配器的添加:

     public Retrofit build() {
         ...
          Executor callbackExecutor = this.callbackExecutor;
          if (callbackExecutor == null) {
            callbackExecutor = platform.defaultCallbackExecutor();
          }
    
          List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
          //添加适配器callAdapter
          callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
         ...
          return new Retrofit(
              callFactory,
              baseUrl,
              unmodifiableList(converterFactories),
              unmodifiableList(callAdapterFactories),
              callbackExecutor,
              validateEagerly);
        }
    

    platform.defaultCallAdapterFactories 指的是 Android 平台的一个默认的适配器工厂,当我们不使用自定义适配器工厂时,则添加的就是这默认的工厂。这里提到了自定义适配器工厂,其实我们在使用 Retrofit 的时候,有时候会和RxJava 结合,例如在创建 Retrofit 时,也会 addCallAdapterFactory,将RxJava2CallAdapterFactory 添加到 callAdapterFactories 中。

    mRetrofit = new Retrofit.Builder()
                    .client(okHttpClient)
                    .baseUrl(baseUrl)
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .build();
    

    添加调用适配器工厂的目的就是支持 Call 以外的服务方法返回类型,如支持ObservableSingle 返回类型等。 在 callAdapterFactories 集合器添加一个默认适配器工厂时,也附带传进去了一个参数 callbackExecutorcallbackExecutor 是 Java8 或者 Android 平台的一个默认线程调度器,它的作用涉及到一个线程切换的问题,也就是后续需要分析的 Retrofit 是如何将子线程切换到主线程?⁉️

    在上面源码创建 CallAdapter时,有一个对象也同时被创建,那就是Converter

    Converter<ResponseBody, ResponseT> responseConverter = createResponseConverter(retrofit, method, responseType);
    

    Converter 数据装换器。它的添加和获取方式和 CallAdapter 类似。在Retrofit 初始化时添加到 List<Converter.Factory> 工厂集合,根据类型 Type 取出不同的 Converter,对返回的网络响应,做出数据的转换,例如转换成实体类。基本逻辑与 CallAdapter 类似。

    mRetrofit = new Retrofit.Builder()
                    .client(mOkHttpClient)
                    .baseUrl(baseUrl)
                    .addConverterFactory(GsonConverterFactory.create()
                    .build();
    

    总结一下上面讲的:

    1,一开始动态代理中调用 loadServiceMethod 方法,解析接口方法中的注解,参数,头部信息等;

    2,依据接口方法的返回类型,从适配器工厂集合里进行查询,生成相应的适配器 CallAdapter,区分是 RxJavaObservableSingle 还是 Call 或者其他类型,(适配器工厂集合的数据是由构建 RetrofitaddCallAdapterFactory() 添加,如无自定义,则添加 Android 平台默认适配器)。以相同的方式取出数据转换器 Converter

    3,利用上面生成的 CallAdapter,调用 invoke 方法,创建 OkHttpCall 对象,即针对请求信息,利用 OkHttp 进行异步或者同步网络请求,并且对响应结果进行实体类转换;

    4,创建好 OkHttpCall 后,又利用上面查询到的适配器 CallAdapter 调用adapt,返回 RxJavaObservableSingle 或者 Call 对象。

    Retrofit 是如何将子线程切换到主线程?

    在添加默认适配器工厂 defaultCallAdapterFactories 时,将 callbackExecutor 作为了一个参数,那么它的具体实现也就是在这个默认适配器工厂中。 我们来看下 callbackExecutor 在里面做了些啥。

    static final class ExecutorCallbackCall<T> implements Call<T> {
        final Executor callbackExecutor;
        final Call<T> delegate;
        ...
    
        @Override
        public void enqueue(final Callback<T> callback) {
    
          delegate.enqueue(
              new Callback<T>() {
                @Override
                public void onResponse(Call<T> call, final Response<T> response) {
                  callbackExecutor.execute(
                      () -> {
                        if (delegate.isCanceled()) {
                          // Emulate OkHttp's behavior of throwing/delivering an IOException on
                          // cancellation.
                          callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
                        } else {
                          callback.onResponse(ExecutorCallbackCall.this, response);
                        }
                      });
                }
    
                @Override
                public void onFailure(Call<T> call, final Throwable t) {
                  callbackExecutor.execute(() -> callback.onFailure(ExecutorCallbackCall.this, t));
                }
              });
        }
    

    在上述代码里了解到,callbackExecutorExecutor,一个线程调度器。在Call 的 enqueue 实现里执行了一个异步网络请求 delegate.enqueue,在请求的响应 onResponseonFailureExecutor 也同样执行了一个线程,这里就有个疑问,为什么要在一个异步请求里又调用一个线程?我们知道callbackExecutor 是一个线程调度器,那他内部到底实现的是什么?
    默认 callbackExecutor 的创建在 Retrofit 的初始化中,callbackExecutor = platform.defaultCallbackExecutor();

    static final class Android extends Platform {
    
        @Override
        public Executor defaultCallbackExecutor() {
          return new MainThreadExecutor();
        }
    
        static final class MainThreadExecutor implements Executor {
          private final Handler handler = new Handler(Looper.getMainLooper());
    
          @Override
          public void execute(Runnable r) {
            handler.post(r);
          }
        }
      }
    }
    

    platform 是一个 Android 平台,defaultCallbackExecutor 内部其实调用的是 new MainThreadExecutor() ,很清楚的看到, handler.post(r) 内部使用Handler将响应抛到了主线程。这就是 Retrofit 将子线程切换到主线程的核心所在。

    Retrofit 为什么要使用动态代理?

    动态代理的优势是什么?不用暴露真实的委托者,根据不同的委托创建不同的代理,通过代理去做事情。

    那 Retrofit 弥补了OkHttp 的哪些缺点呢?

    OkHttp 在使用的时候,请求参数的配置是不是很繁琐,尤其当有一些表单提交时,又臭又长,而 Retrofit 就是弥补了这个缺点,利用 @GET、@POST、@Path、@Body 等注解以及一些参数很简便的就构造出了请求。

    当 Retrofit 创建了不同的接口,动态代理就发挥出了作用。每当不同接口方法执行时,动态代理都会拦截该请求,对接口中的注解,参数进行解析,构建出不同的 Request,最后则交给 OkHttp 去真正执行。

    Retrofit 结合动态代理,不用关心真正的接口方法,对符合规范的接口进行统一化的管理,以统一的方式解析注解和参数,拼接成 request。

    总结:

    Retrofit 其实是 OkHttp 的封装类,内部网络请求靠的还是 OkHttp,那 Retrofit 封装后改变了什么?

    • 接口请求更加简便,标注注解 @GET、@POST、@Path、@Body 等就形成一个网络请求;

    • 默认帮助开发者解析 responseBody,另外还可以自定义解析策略;

    • Retrofit 帮助开发者进行线程切换;

    • Retrofit 带给开发者更多的权限,可自定义适配网络请求。

    相关文章

      网友评论

        本文标题:读懂 Retrofit 原理~

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