zoukankan      html  css  js  c++  java
  • Retrofit执行流程以及源代码分析详解

    一、概述

      Retrofit目前是Android网络请求中非常流行的一个框架。为什么这么流行?那就要从行业内的各位大佬的技术选型开始。我们一般在做技术选型的时候会参考以下几个标准:

      1.框架是否能解决我们的问题

      2.框架是否稳定

      3.框架是否易用

      根据以上三点,我们来谈谈为什么要用这个框架。

      1.解决问题能力

        a.可以随意切换httpClient来实现网络请求,如:OkHttp、httpClient等

        b.其支持多种数据解析工厂Convert.Factory。如利用GsonConvertFactory.create()来解析从服务端返回的json为对象。这就避免了我们手动解析从而节省开发时间。另外我们还可以根据Convert.Factory自定义数据解析工厂来实现我们的个性化解析,使用的时候只需要在retrofit对象中添加这个数据解析工厂就能再项目中快速使用。如果需求再次变更,切换到另外一种数据解析工厂即可。

        c.支持多种网络请求工厂适配器,如:ExecutorCallAdapterFactory.create()或者RxJava2CallAdapterFactory.create()。前者是retrofit2的默认网络请求适配器,后者是RxJava2适配器,加入之后用户就可以很方便的使用RxJava2的能力了。除此之外如果业务上有一些特殊的需求,需要定制其他的网络适配器的时候也非常的方便。

        d.retrofit2的底层网络请求默认使用的是OkHttp框架,这让retrofit2天生具有了OkHttp的各种高性能的特性(okhttp会单独拉出来一节具体你说明,本节不再赘述)

        e.解耦

      2.框架的稳定性

        retrofit2的目前是Android领域中非常主流的一个网络请求适配器工厂。其稳定性已经得到了各大厂商的验证。稳定性方面无需担心。

      3.框架是否易用  

        retrofit2框架使用起来非常的方便,使用的过程中只需要一行链式调用就能解决问题。下面给出一个简单的小例子供大家一观:

    private void retrofitTest() {
            //创建一个Retrofit
            Retrofit retrofit = new Retrofit.Builder().
                    baseUrl("http://www.xxxx.com/").//请求地址
                    addConverterFactory(GsonConverterFactory.create()).//网络请求结果转换器
                    addCallAdapterFactory(RxJava2CallAdapterFactory.create()).//网络请求适配器
                    build();
            //创建一个登录接口
            ApiLoginClassService apiLoginClassService = retrofit.create(ApiLoginClassService.class);
            Map<String, String> map = new HashMap<>();
            map.put("userName", "13333333333");
            map.put("password", "123456");
            //获取call对象
            Call<String> call = apiLoginClassService.login(map);
            //执行请求方法,并监听回调结果
            call.enqueue(new Callback<String>() {
                @Override
                public void onResponse(Call<String> call, Response<String> response) {
                    //网络请求成功回调
                }
    
                @Override
                public void onFailure(Call<String> call, Throwable t) {
                    //网络请求失败回调
                }
            });
    
    
        }
    

      为了方便下面的源码分析,我把retrofit调用登录接口的步骤都拆分了,但是在使用过程中大家完全可以通过...实现链式调用,使用非常的简单。

      上面的例子调用步骤为:1.首先创建一个retrofit2对象,并设置其要请求的主机地址、设置网络请求结果数据转换器、设置网络请求适配器、调用build()方法完成创建。2.通过retrofit对象获取接口实例。3.通过接口实例调用登录接口(login)并返回一个Call对象(call是一个请求对象)。4.通过Call对象来发起网络请求,并回调其成功与失败的回调方法。

      下面就通过以上四步按步骤来分析retrofit2的源代码已经其执行流程。

    二、代码分析

      代码分析分为四步,1.retrofit2对象的创建 2.接口实例的生成 3.创建call对象 4.发起网络请求

      1.创建Retrofit对象

        Retrofit对象是通过建造者模式进行创建的,如下代码所示

    Retrofit retrofit = new Retrofit.Builder().
                    baseUrl("http://www.xxxx.com/").//请求地址
                    addConverterFactory(GsonConverterFactory.create()).//网络请求结果转换器
                    addCallAdapterFactory(RxJava2CallAdapterFactory.create()).//网络请求适配器
                    build();
    

      1.1.先看下期内部类Builder()的构造方法

      

      public static final class Builder {
        //用于生成一个请求结果回调器
        private final Platform platform;
        //网络请求工厂
        private @Nullable okhttp3.Call.Factory callFactory;
        //网络请求的主路径,必须以”/“结尾
        private @Nullable HttpUrl baseUrl;
        //请求结果数据转换器,把服务端返回的数据通过转换器转换为对象,如:GsonConvertFactory.create()
        private final List<Converter.Factory> converterFactories = new ArrayList<>();
        //网络请求适配器,如:适配OkHttp的call,以及RxJava的Observable
        private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
        //网络请求结果回调器
        private @Nullable Executor callbackExecutor;
        //是否提前对业务接口中的注解进行转换,这个在retrofit中会用到
        private boolean validateEagerly;
        Builder(Platform platform) {
          this.platform = platform;
        }
        public Builder() {
          this(Platform.get());
        }
    

      Builder的构造方法非常简单,也就是设置了一个Platform对象。Platform对象的get方法返回了一个请求结果回调器,表明这个请求结果在主线程中运行

      1.2.Platform

    private static final Platform PLATFORM = findPlatform();
    
      static Platform get() {
        return PLATFORM;
      }
    
      private static Platform findPlatform() {
        try {
          Class.forName("android.os.Build");
          if (Build.VERSION.SDK_INT != 0) {
            return new Android();
          }
        } catch (ClassNotFoundException ignored) {
        }
        return new Platform(true);
      }
    

      Android类是Platform的内部类,其作用就是返回一个在主线程中执行的回调器,相关的解释在代码中有注释,这里就不再赘述了

      static final class Android extends Platform {
        Android() {
          super(Build.VERSION.SDK_INT >= 24);
        }
        //请求结果回调,使请求结果在主线程中执行
        @Override public Executor defaultCallbackExecutor() {
          return new MainThreadExecutor();
        }
    
        static class MainThreadExecutor implements Executor {
          //根据主线程Looper.getMainLopper获取主线程Handler
          private final Handler handler = new Handler(Looper.getMainLooper());
          //在主线程执行Runnable,这里的r指的就是请求结果的回调方法
          @Override public void execute(Runnable r) {
            handler.post(r);
          }
        }
      }
    

      1.3.baseUrl的作用是解析传入的url参数,并给Builder的HttpUrl赋值。并返回一个Builder对象(this)  

     public Builder baseUrl(HttpUrl baseUrl) {
          Objects.requireNonNull(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;
        }
    

      1.4.addConvertFactory,其目的是设置网络请求结果的转换器,把请求结果转换为我们需要的格式,这里将利用Gson转为换实体对象,代码非常简单就是把数据转换工厂添加到工厂集合中。我们看下其代码的具体实现

       public Builder addConverterFactory(Converter.Factory factory) {
          converterFactories.add(Objects.requireNonNull(factory, "factory == null"));
          return this;
        }
    

      1.5.addCallAdapterFactory,其目的是设置网络请求适配器,源代码也非常简单,只是把适配器加入工厂而已。

     public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
          callAdapterFactories.add(Objects.requireNonNull(factory, "factory == null"));
          return this;
        }
    

      1.6.看下其build()方法

      

    public Retrofit build() {
          if (baseUrl == null) {
            throw new IllegalStateException("Base URL required.");
          }
          //如果没有设置网络请求工厂,默认使用OkHttpClient
          okhttp3.Call.Factory callFactory = this.callFactory;
          if (callFactory == null) {
            callFactory = new OkHttpClient();
          }
          //回调方法执行器,如果没有设置就使用默认的,默认为MainThreadExecutor
          Executor callbackExecutor = this.callbackExecutor;
          if (callbackExecutor == null) {
            callbackExecutor = platform.defaultCallbackExecutor();
          }
          //添加网络请求适配器
          List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
          callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
          // 数据转换工厂集合
          List<Converter.Factory> converterFactories = new ArrayList<>(
              1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
          //添加数据转换工厂
          converterFactories.add(new BuiltInConverters());
          converterFactories.addAll(this.converterFactories);
          converterFactories.addAll(platform.defaultConverterFactories());
          //将builder中的数据给Retrofit
          return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
              unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
        }
    

      build()方法中做的事情非常的简单,只做了一些数据的初始化,并把初始化数据传递给Retrofit。例如:通过new OkHttpClient初始化一个请求工厂,通过platform.defaultCallbackExecutor初始化一个请求结果回调器,其实这里指的就是MainThreadExecutor,再有就是通过callAdaperFactories添加网络适配器工厂,通过coverterFactories添加数据转换工厂,最终通过new Retrofit对象把初始化的数据加入到retrofit。就这么简单。

    总结:Retrofit的创建其实就是对Builder做一些配置信息,然后把这些初始化的配置信息赋值给Retrofit的过程而已,并没有做什么特殊的处理,大家可以仔细回味一下再接着往下看,最起码要保证创建Retrofit这个链条的流程是完全懂了。

      2.调用create方法生成接口实例

     //创建一个登录接口
            ApiLoginClassService apiLoginClassService = retrofit.create(ApiLoginClassService.class);
    

      2.1以上的方法会返回一个接口实例,我们主要看一下create方法的源代码

      public <T> T create(final Class<T> service) {
        validateServiceInterface(service);
        //利用java.lang.reflect.Proxy实现动态代理并返回一个接口对象,
        //此处需要注意的是动态代理只能代理接口
        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 the method is a method from Object then defer to normal invocation.
                if (method.getDeclaringClass() == Object.class) {
                  return method.invoke(this, args);
                }
                //此处在android平台上不走
                if (platform.isDefaultMethod(method)) {
                  return platform.invokeDefaultMethod(method, service, proxy, args);
                }
                //此处是代理独对象真正要走的地方,此处return返回的是一个网络请求对象或者网络请求适配器,也就是案例中国的Call对象,如果
                //网络适配器设置的是RxJava2CallAdapterFactory.create(),则此处返回的是一个Observable对象
                return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
              }
            });
      }
    

      此处使用动态代理,ApiLoginClassService接口返回一个ApiLoginClassService接口实例,相关的说明已在源码中做了注释,这里就不再赘述了

      3.创建Call对象

        调用ApiLoginClassService的login方法创建一个用于网络请求的Call对象

     //获取call对象
            Call<String> call = apiLoginClassService.login(map);
    

      3.1.这里调用login,其实最终调用的是retrofit.create(class)方法中的代理对象的InvocationHandler的LoadServiceMethod(method).invoke方法

    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) {
            //解析Method中的注解
            result = ServiceMethod.parseAnnotations(this, method);
            serviceMethodCache.put(method, result);
          }
        }
        return result;
      }
    

      loadServiceMethod的首先会从缓存中检查是否有ServiceMethod对象,如果有就直接用,如果没有就创建一个并返回

      3.2.ServiceMethod类是一个抽象类里面包含了一个抽象方法invoke,和一个解析注解的方法parseAnnotations,其通过RequestFactory解析method中的注解并封装成HttpServiceMethod返回。其实现类是HttpServiceMethod 

    abstract class ServiceMethod<T> {
      static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
        RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
    
        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);
      }
    
      abstract @Nullable T invoke(Object[] args);
    }
    

      3.3.RequestFactory

      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); } .......     //对参数注解进行解析,解析完成后存入parameerHandlers中 int parameterCount = parameterAnnotationsArray.length; parameterHandlers = new ParameterHandler<?>[parameterCount]; for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) { parameterHandlers[p] = parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter); } ....
       ..... return new RequestFactory(this); }

      parseMethodAnnotation方法

    //解析注解
        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());
    

      

    //获取方法注解,得到注解的值,并赋值给RequestFactory的全局变量,httpMethod=httpMethod,relativeUrl=value
        private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
          .....
        //http请求的方法 this.httpMethod = httpMethod; this.hasBody = hasBody;     ....
        //http请求路径 this.relativeUrl = value;
        //请求参数 this.relativeUrlParamNames = parsePathParameters(value); }

       注解是如何解析的已经看完了,接下来看一下HttpServiceMethod具体干了一些什么事情。实际上HttpServiceMethod是一个抽象类,在其内部做了非常多的初始化动作。如:创建网络请求适配器CallAdapter、创建请求结果数据转换器,responseConverter、创建call请求工厂callFactory

    static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
          Retrofit retrofit, Method method, RequestFactory requestFactory) {
        Annotation[] annotations = method.getAnnotations();
        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) {
            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);
        } else if (continuationWantsResponse) {
          //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
          return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForResponse<>(requestFactory,
              callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
        } else {
          //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
          return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForBody<>(requestFactory,
              callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
              continuationBodyNullable);
        }
      }
    

      从以上的源码可以看出不管是创建网络请求适配器还是响应结果转换器,都是通过调用retrofit来实现的。最终把初始后的数据通过HttpServiceMethod对象的形式返回

     3.5.loadServiceMethod(method).invoke(map)

      由于ServiceMethod类是一个抽象类,里面定义了invoke方法。其实现类HttpServiceMethod也是一个抽象类,里面定了了adapt方法,并实现了invoke方法,其invoke方法又调用了adapt方法。而adapt方是CallAdapter的方法。源码如下:

    ServiceMethod.java

    abstract class ServiceMethod<T> {
      abstract @Nullable T invoke(Object[] args);
    }
    

      HttpServiceMethod.java,可以看到其的确实现了invoke方法并调用了自身的adapt抽象方法。

      @Override final @Nullable ReturnT invoke(Object[] args) {
        Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
        return adapt(call, args);
      }
    
      protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);
    

      那么HttpServiceMethod的具体实现是那个类呢?其真正的实现类是CallAdapted,源码如下:

    static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
        private final CallAdapter<ResponseT, ReturnT> callAdapter;
    
        CallAdapted(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
            Converter<ResponseBody, ResponseT> responseConverter,
            CallAdapter<ResponseT, ReturnT> callAdapter) {
          super(requestFactory, callFactory, responseConverter);
          this.callAdapter = callAdapter;
        }
    
        @Override protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
          return callAdapter.adapt(call);
        }
      }
    

      我们从上面可以看到HttpServiceMethod的具体实现类是CallAdapted类,并且其实现了adapt方法,并调用callAdapter网络适配器的adapt方法来返回一个call对象。参数中传递的call其实是OkHttpCall对对象,其在invoke方法中通过new关键字实例化而得到的

      下面看一下CallAdapter的具体实现类DefaultCallAdapterFactory中的adapt方法的具体实现。下面是DefaultCallAdapterFactory的adapt方法的具体实现

      @Override public @Nullable CallAdapter<?, ?> get(
          Type returnType, Annotation[] annotations, Retrofit retrofit) {
        if (getRawType(returnType) != Call.class) {
          return null;
        }
        if (!(returnType instanceof ParameterizedType)) {
          throw new IllegalArgumentException(
              "Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
        }
        final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);
    
        final Executor executor = Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
            ? null
            : callbackExecutor;
    
        return new CallAdapter<Object, Call<?>>() {
          @Override public Type responseType() {
            return responseType;
          }
          //返回了一个ExecutorCallbackCall对象
          @Override public Call<Object> adapt(Call<Object> call) {
            return executor == null
                ? call
                : new ExecutorCallbackCall<>(executor, call);
          }
        };
      }
    

      从上面的源码我们可以看出adapt方法仅仅是返回了一个ExecutorCallbackCall对象。而ExecutorCallbackCall对象实现了Call类并实现了其enqueue、execute以及request方法。源码如下所示

    static final class ExecutorCallbackCall<T> implements Call<T> {
        final Executor callbackExecutor;
        final Call<T> delegate;
    
        ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
          this.callbackExecutor = callbackExecutor;
          this.delegate = delegate;
        }
    
        @Override public void enqueue(final Callback<T> callback) {
          Objects.requireNonNull(callback, "callback == null");
    
          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));
            }
          });
        }
    
        @Override public boolean isExecuted() {
          return delegate.isExecuted();
        }
    
        @Override public Response<T> execute() throws IOException {
          return delegate.execute();
        }
    
        @Override public void cancel() {
          delegate.cancel();
        }
    
        @Override public boolean isCanceled() {
          return delegate.isCanceled();
        }
    
        @SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
        @Override public Call<T> clone() {
          return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
        }
    
        @Override public Request request() {
          return delegate.request();
        }
      }

      总结,我们回顾一下loadServiceMethod(method).invoke(map)都干了些啥。

      1.通过loadServiceMethod方法返回了一个ServiceMethod类,ServiceMethod类是一个抽象类其具体的实现是HttpServiceMethod,而HttpServiceMethod也是一个抽象类,其具体的实现是CallAdapted类。ServiceMethod类解析method的注解,并将其封装成为RequestFactory,并把RequestFactory封装到HttpServiceMethod中。而在HttpServiceMethod初始化了RequestFactory、CallAdapter、callFactory以及Converter,并将以上参数传递给CallAdapted类,所以最终的loadServiceMethod最终返回的是CallAdapted类。而loadServiceMethod(method).invoke(map)则会调用其adapt方法,而CallAdapted类实现了HttpServiceMethod类的抽象方法adapt,在adapt内部又调用了DefaultCallAdapterFactory的adapt方法,并最终返回了一个ExecutorCallbackCall类,此类实现Call接口,到此为止我们想要的Call对象已经返回了。不晓得大家是否看明白了,如果没明白就是我没说清楚【尴尬】

      4.通过Call对象发起网络请求

        通过调用call对象的enqueue方法发起网络请求,并监听其回调结果,示例代码如下:

    //执行请求方法,并监听回调结果
            call.enqueue(new Callback<String>() {
                @Override
                public void onResponse(Call<String> call, Response<String> response) {
                    //网络请求成功回调
                }
    
                @Override
                public void onFailure(Call<String> call, Throwable t) {
                    //网络请求失败回调
                }
            });
    

      这里的call.enqueue方法中的call指的就是3中的ExecutorCallbackCall类中的enqueue方法

    static final class ExecutorCallbackCall<T> implements Call<T> {
        final Executor callbackExecutor;
        final Call<T> delegate;
    
        ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
          this.callbackExecutor = callbackExecutor;
          this.delegate = delegate;
        }
    
        @Override public void enqueue(final Callback<T> callback) {
          Objects.requireNonNull(callback, "callback == null");
    
          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));
            }
          });
        }
    

      我们看下两个重要的参数Executor callbackExecutor和Call<T> delegate。callbackExecutor很好理解,指的是请求结果回调类MainThreadExecutor类,其executor(Runnable r)方法运行在主线程中。所以由于onResponse方法外城包裹着callbackExecutor.executor方法,所以其内部的回调函数,如:onResponse和onFailure方法也会运行在主线程中。

    到此为止Retrofit2从创建到方法执行到最终的返回结果的一整套执行流程就已经分析完毕了。我们再来总结回顾一下整个流程。还是分四步来总结。

      1.创建Retrofit对象,通过调用器内部类通过建造者模式设置一些初始化的配置,如设置主机地址baseUrl、设置请求结果转换器GsonConvertFactory.create()、设置网络请求适配器DefaultCallAdapterFactory.create(),然后调用build()方法把这些配置统统赋值给Retrofit,然后retrofit就算是创建完成了。

      2.创建接口实例是通过retrofit.create(ApiLoginClassService.class)来创建一个ApiLoginClassService实例。在create方法中通过动态代理java.lang.reflect.Proxy.newProxyInstance来创建接口实例,并实现其InvocationHandler来实现接口方法的赋值。

      3.创建Call对象则是通过apiLoginClassService.login(map)来创建了,其这正的执行过程是InvocationHandler中的invoke方法中的loadServiceMethod(method).invoke(map)方法来返回一个ExecutorCallbackCall对象,此对象实现Call接口。其实最主要的是通过loadServiceMethod通过层层包装返回一个ServiceMethod对象(HttpServiceMethod、CallAdapted),并通过调用其invoke方法通过层层调用最红调用到DefaultExecutorCallAdapterFactory中的adapt方法并最终返回一个ExecutorCallbackCall类。

      4.发起网络调用的是通过Call的enqueue方法来实现的。其具体的调用过程如下,通过调用ExecutorCallbackCall.enqueue(callback)来实现做种的调用,其中在enqueue方法中会首选调用Executor=MainThreadExecutor进行主线程运行包裹,然后会调用callback的onResponse和onFailure,最终让回调函数在主线程中执行。

    ps:分析到这一步已经算是吧Retrofit的源代码的执行流程分析完成了,但是总感觉还是缺少了点啥。哦哦哦,对了。1.忘记分析GsonConvertFactory.create()的具体实现过程已经执行流程。2.RxJava2CallAdapterFactory.create()网络适配器的实现以及执行过程。因为这篇这篇文章实在是天长了,怕大家在中途读的过程中被全返,所以以上两点的实现方式以及执行流程会放到下一小节去分析。敬请期待。

      

  • 相关阅读:
    五子棋
    团队项目:五子棋
    101空降师506团2营E连全体成员
    团队作业七
    作业六
    团队作业(五)——旅游行业的手机App
    团队任务四(无图)
    团队作业三(补二)
    菜的抠脚团队正式成立
    团队作业七
  • 原文地址:https://www.cnblogs.com/tony-yang-flutter/p/12361914.html
Copyright © 2011-2022 走看看