【Android】Retrofit的深度、高质量学习

1 Retrofit数据解析器、url、网络请求适配器等

参考:链接:https://www.jianshu.com/p/d9ffdf3b04c3

  • Retrofit是RESTful的HTTP网络请求框架的封装。

  • 网络请求的工作本质上是okHttp完成的,而retrofit仅负责网络请求接口的封装。

使用步骤

1.创建描述网络请求的接口

在内部通过注解描述网络请求的参数和配置网络请求参数。

public interface retrofit_interface {
    @GET("部分URL")
    Call<Person> getCall();
}

在这个接口内定义了一个getCall()方法,返回值是个Call类型的泛型,他把表示的是接收数据的类在内部定义了个Bean 。

这就是第一步,定义一个接口,然后在接口中定义一个方法和相应的注解。

其实第一步非常关键,因为Retrofit内部会通过动态代理的模式将我们的接口以及注解转换成一个http请求,最后在去执行http请求。

还有一点就是:接口中的每一个方法还有他的参数都需要使用注解来标注,不标注会出错。

2.创建retrofit实例

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://www.sina.com/") // 设置网络请求的Url地址
        .addConverterFactory(GsonConverterFactory.create()) // 设置数据解析器
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 支持RxJava平台
        .build();

一个Retrofit他完整的url包含两部分,一个是在baseUrl中,还有一个是在接口中添加注解时设置的。

addConverterFactory添加一个数据解析的工厂,由这个数据解析的工厂生产数据解析器,用来解析服务器返回给我们的数据。

addCallAdapterFactory添加网络请求适配器的工厂,其实作用都是一样的,通过工厂模式生产我们的网络请求适配器。因为Retrofit支持多种网络请求适配器的方式,比如Java8,RxJava等等,这时候系统就会根据我们需要的 场景选择不同网络请求的适配器。

3.创建网络请求接口实例并配置网络请求参数

	// 创建 网络请求接口 的实例
    retrofit_interface request = retrofit.create(retrofit_interface.class);
    // 对 发送请求 进行封装
    Call<Person> call = request.getCall();

调用Retrofit的create方法,并将前面的接口传进来,其实就是获取前面接口定义好的一个对象,然后调用接口中定义好的方法getCall()来获取我们的Call对象。这个Call对象非常重要,它是用于发送网络请求所需要的。

4.发送网络请求

public void callRequest() {
   //发送网络请求(异步)
    call.enqueue(new Callback<Person>() {
        //请求成功时回调
        @Override
        public void onResponse(Call<Person> call, Response<Person> response) {
            // 对返回数据进行处理
            response.body();
        }

        //请求失败时候的回调
        @Override
        public void onFailure(Call<Person> call, Throwable throwable) {
            System.out.println("连接失败");
        }
    });
}

在这里模仿了一个异步网络请求的方法,他的请求方法和okhttp是一致的。因为Retrofit网络请求本质上都是由okhttp来做的,Retrofit只是对我们网络请求的一个接口进行一个封装。(包括对参数的一个设置,头部信息,url等等)

5.处理服务器返回的数据

通过callback接口返回两个方法,在成功或失败的方法内做出相应的处理

2 Retrofit源码解读:serviceMethod、工厂模式、回调执行器等

Retrofit本质上是交给okhttp解读的,Retrofit就是通过对接口层的封装,将我们请求的参数,头部,url这些网络请求的信息封装。然后交给okhttp进行实际的请求操作。在服务端返回数据之后,okhttp又将原始的结果交给Retrofit,而Retrofit根据不同的场景进行不同的数据解析方式。

  1. 解析网络请求接口的注解配置网络请求参数

  2. 动态代理生成网络请求对象

  3. 网络请求适配器将网络请求对象进行平台适配

  4. 网络请求执行器发送网络请求

  5. 数据转换器 解析服务器返回的数据

  6. 回调执行器切换线程

  7. 主线程处理返回结果

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://www.sina.com/") // 设置网络请求的Url地址
        .addConverterFactory(GsonConverterFactory.create()) // 设置数据解析器
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 支持RxJava平台
        .build();

创建Retrofit实例是通过build构建者来完成的。什么是构建者模式呢?如果这个对象非常复杂,我们将这个对象的构建和表示相分离,就可以不用知道Retrofit非常复杂的对象在内部非常复杂的创建细节的情况下就可以直接创建这个复杂对象。

看一下Retrofit:

public final class Retrofit {


看一下里面定义的一些变量,首先是LinkedHashMap.这个map是用来配置网络请求配置对象的。
什么是配置对象?就是他会对我们网络请求接口中的方法以及他的注解进行解析,解析之后获得的对象就会放在这里面。
这个LinkedHashMap它的作用就是:存储网络请求相关的一些配置,
包括一些网络请求的方法,数据转换器,网络请求适配器,网络请求工厂以及URL地址等等都放在这个map当中。
serviceMethodCache集合中有一个很重要的对象serviceMethod,这个对象就是包含所有网络请求信息的对象。
  private final Map<Method, ServiceMethod> serviceMethodCache = new LinkedHashMap<>();


callFactory 网络请求的工厂,就是生产call请求对象的,而这个call请求就是网路请求器,不管是同步还是异步都是通过这个call来调用的,而在Retrofit默认就是okhttp请求方式。
  private final okhttp3.Call.Factory callFactory;


baseUrl是网络请求的地址。
  private final HttpUrl baseUrl;


converterFactories是数据转换器工厂的集合,作用就是放置数据转换器工厂,而数据转换器工厂就是生产数据转换器Converter的。
Converter就是比如说服务器返回数据给json类型对象,然后通过json解析器来进行解析,并在主线程当中去显示。
  private final List<Converter.Factory> converterFactories;


adapterFactories是网络请求适配器工厂的集合,用于放置网络请求适配器的工厂,
而网络请求适配器的工厂就是用于生产网络请求适配器的。
  private final List<CallAdapter.Factory> adapterFactories;


converterFactories 和 adapterFactories这两个集合都是通过工厂模式来创造的,
工厂模式就是将类的实例化操作和使用对象的操作相分开,
就是他可以让用户不知道具体参数就可以直接实例化我们需要的对象。 



Executor回调方法的执行器,
我们从子线程切换到主线程,再从主线程切换到子线程都通过Executor来进行的。
  private final Executor callbackExecutor;



validateEagerly这个标志为用来判断是否提前对接口中的注解进行转换的标志位。
  private final boolean validateEagerly;
  ...
}

成功建立一个Retrofit的标准其实就是这样几个变量。

3 Retrofit源码解读:callAdapter、GsonConverter等

链接:https://www.jianshu.com/p/306f0415977d

  private final Map<Method, ServiceMethod> serviceMethodCache = new LinkedHashMap<>();

  private final okhttp3.Call.Factory callFactory;
  private final HttpUrl baseUrl;
  private final List<Converter.Factory> converterFactories;

这里:
  private final List<CallAdapter.Factory> adapterFactories;  
  private final Executor callbackExecutor;
  private final boolean validateEagerly;

adapterFactories中这个Factory就是生产CallAdapter的。

CallAdapter就是将网络请求执行器转换成不同平台所适用的。

看一下Factory:它就是定义在CallAdapter中的抽象类Factory。

abstract class Factory {
  
    public abstract CallAdapter<?> get(Type returnType, Annotation[] annotations,
        Retrofit retrofit);

    protected static Type getParameterUpperBound(int index, ParameterizedType type) {
      return Utils.getParameterUpperBound(index, type);
    }

    protected static Class<?> getRawType(Type type) {
      return Utils.getRawType(type);
    }
  }

Factory默认情况下的三种实现:
在这里插入图片描述
这个Factory默认情况下有三种实现。作用就是将默认的网络请求执行器,okHttpCall转换成适合被不同平台用来调用网络请求执行器的格式。

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://www.sina.com/") // 设置网络请求的Url地址
        .addConverterFactory(GsonConverterFactory.create()) // 设置数据解析器
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 支持RxJava平台

这里:
        .build();

build:

public Retrofit build() {

前面是一个非空的判断。
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }


然后默认情况下是使用okhttp进行的,
他会把他的成员变量callFactory赋值给callFactory对象,就是说如果没有指定,就调用ok来进行请求。
这也就验证了Retrofit只是对网络接口请求的一个封装而已,实质还是要使用okhttp。
如果这个callFactory对象为空的话,就创建一个OkHttpClient。
      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }


Executor:如果没有指定,就会使用默认的callbackExecutor。
callbackExecutor就是一种主线程切换到子线程的一种执行器。
如果他为空的话就会调用defaultCallbackExecutor进行赋值。
      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }


这里向集合中添加CallAdapter.Factory的请求适配器。
      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));


然后又会去新建一个数据转换器的工厂集合。在这个集合当中存储的就是默认的数据转换器工厂。
      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);



adapterFactories和converterFactories这两个数据集合类,
都是获取合适的网络请求适配器,数据转换器,
但是他们的存储方式都是从首位到末位开始遍历的。
在集合中位置越靠前意味着有越高的使用权限。



调用build之后会返回一个Retrofit对象,并配入上述已经配置好的成员变量。
完成这最后一步的话,就完成了整个Retrofit的创建。
      return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
          callbackExecutor, validateEagerly);
    }
  }

4 Retrofit源码解读:网络请求接口实例创建

链接:https://www.jianshu.com/p/14c621231dc0

public interface retrofit_interface {
    @GET("部分URL")
    Call<Person> getCall();
}

我们使用Retrofit进行网络请求要定义网络请求的接口类。并在接口类中添加一个方法,这个方法添加了GET注解。这个GET很好理解,代表着整个Http请求通过GET来获取网络数据的。

这里Url分为两个部分,一是baseUrl,二是接口类中等GET注解后面跟的Url。如果这个Url是个完整路径,那么baseUrl就不用设置了。

如何创建网络接口的实例?

	Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://www.sina.com/") // 设置网络请求的Url地址
        .addConverterFactory(GsonConverterFactory.create()) // 设置数据解析器
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 支持RxJava平台
        .build();

    // 创建 网络请求接口 的实例
    retrofit_interface request = retrofit.create(retrofit_interface.class);

调用retrofit.create()的create方法后,完成网络接口的实例创建。这个create内部使用了观察者模式、代理模式、外观模式。通过网络接口里的设置,我们可以使用注解进行相应的配置。

public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }


动态代理就是动态的生成网络请求接口的动态代理类。
然后将这个代理类创建好之后交给InvocationHandler类来处理,
然后复写invoke这个方法来做实际的网络请求拦截的操作。
InvocationHandler作为具体的实现,最终会返回给我们一个动态代理的对象,
而整个生成实例的过程中,还有生成实现的缓存机制。
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          private final Platform platform = Platform.get();

一旦调用了接口中的getCall()方法,就会执行这个invoke()方法,来进行网络请求的拦截:
          @Override public Object invoke(Object proxy, Method method, 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);
            }


invoke()方法,最核心的3行代码:

loadServiceMethod读取网络请求接口的方法,并根据前面配置好的属性去配置ServiceMethod对象。
ServiceMethod包含了所有请求的属性和信息。
            ServiceMethod serviceMethod = loadServiceMethod(method);


根据创建好的ServiceMethod对象以及前面传递进来的参数去创建OkHttpCall的请求对象。
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);


最后会调用OkHttpCall根据OkHttpCall返回我们需要的对象,
会通过adapter就是网络请求适配器的adapter方法来进行适配的。
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

看一下create方法中判断validateEagerly这个标志位,有一个eagerlyValidateMethods方法:

private void eagerlyValidateMethods(Class<?> service) {
    Platform platform = Platform.get();


这个方法会遍历声明好的方法,然后调用loadServiceMethod这个方法,依次循环遍历都会调用loadServiceMethod这个方法。
loadServiceMethod方法的作用就是他会给我们接口中的每一个方法的注解进行解析,然后存到ServiceMethod这个对象。
ServiceMethod包含封装了网络请求属性的信息,它会将method作为Key值,传入LinkedHashMap集合中。
    for (Method method : service.getDeclaredMethods()) {
      if (!platform.isDefaultMethod(method)) {
        loadServiceMethod(method);
      }
    }
  }

看一下loadServiceMethod:

ServiceMethod loadServiceMethod(Method method) {
    ServiceMethod result;
    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        result = new ServiceMethod.Builder(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

他是在一个单例的形式当中,通过get方法获取到相应的value值,然后将它传入到linkedHashMap中。为什么要使用linkedHashMap?我们通过迭代器调用next方法,这里获取到的是整个集合当中最不经常用到的元素,所以说它也是一种aru算法的实现。

如果不是提前验证的话,这时候就会动态解析对应的方法,然后得到相应的ServiceMethod对象,最后把他存入到集合当中,这种形式也是一种延时加载的形式,也是一种默认状态下的形式。

简单总结

我们创建网络请求接口的实例,首先会调用create方法,然后通过动态代理去拦截网络请求接口当中的生成好的一些方法以及他们的注解,最终会返回一个动态代理对象

5 Retrofit源码解读:serviceMethod和retrofit核心代码

链接:https://www.jianshu.com/p/cf8bce20461b

在Retrofit类中的create()方法里有个拦截方法叫invoke,invoke拦截方法中最核心的三行代码:

ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
  1. 通过loadServiceMeyhod去创建ServiceMethod对象。这个ServiceMethod对象其中包括了网络请求接口的方法以及前面配置好注解的一些属性等等。

  2. 根据创建好的ServiceMethod对象,创建一个实际的网络请求的对象OkHttpCall,用它来同步异步请求的调用。

  3. 会根据ServiceMethod中的成员变量callAdapter(网络请求的适配器),将网络请求进行不同平台的适配,也就是调用adapter这个方法。

首先看一下loadServiceMeyhod

loadServiceMeyhod这个对象就是读取网络请求接口里的方法,并根据前面配置好的属性去配置ServiceMeyhod这个对象。

  ServiceMethod loadServiceMethod(Method method) {
    ServiceMethod result;
    
他会设置一个同步锁,设置一个同步锁就可以保证:
不同的线程,去读取LinkedHashMap缓存的时候,不会造成数据的不安全性。
    synchronized (serviceMethodCache) {


然后调用缓存当中的get方法,
所以说ServiceMeyhod这个类通过单例进行创建,
也就是创建ServiceMeyhod这个对象之前,
他会判断LinkedHashMap缓存当中是否有之前创建过的网络请求实例。
      result = serviceMethodCache.get(method);


如果没有缓存,他就设为空,
调用Builder模式来创建一个ServiceMeyhod对象并放入缓存,就是调用他的put方法将他传入缓存当中。
所以说,创建实例的缓存机制,它的核心做法就是,使用单例模式实现ServiceMeyhod的唯一性,
然后这个ServiceMeyhod对象对应网络请求接口里的方法。
      if (result == null) {
        result = new ServiceMethod.Builder(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

看一下ServiceMeyhod

callFactory:会生成一个call请求的工厂,
这个工厂负责生产OkHttp库里的call对象。
  final okhttp3.Call.Factory callFactory;


callAdapter:网络请求的适配器。
我们从服务端请求出来的数据需要适配不同的平台,包括Android,Java8等等,
这时候就通过callAdapter适配器适配到不同的平台。
  final CallAdapter<?> callAdapter;



baseUrl:网络请求的地址。
  private final HttpUrl baseUrl;



Converter:就是负责把服务器返回给数据转换成泛型为T这个类型。
  private final Converter<ResponseBody, T> responseConverter;



httpMethod:网络请求Http中的方法。
  private final String httpMethod;



relativeUrl:网络请求的相对地址。
baseUrl+relativeUrl就是一个完整的URL地址。
  private final String relativeUrl;



headers:网络请求的Http请求头,是一个键值对的形式。
  private final Headers headers;


contentType:Http网络请求中body的类型。
  private final MediaType contentType;



三个标志位。
  private final boolean hasBody;
  private final boolean isFormEncoded;
  private final boolean isMultipart;



parameterHandler:方法参数的处理器。重要!
作用就是负责解析接口中定义的每一个方法的参数,
然后会构造Http请求时设置参数的一个过程。
  private final ParameterHandler<?>[] parameterHandlers;

ServiceMeyhod包含了访问网络所有的基本信息。

ServiceMeyhod的构造方法:

ServiceMethod(Builder<T> builder) {
    this.callFactory = builder.retrofit.callFactory();
    this.callAdapter = builder.callAdapter;
    this.baseUrl = builder.retrofit.baseUrl();
    this.responseConverter = builder.responseConverter;
    this.httpMethod = builder.httpMethod;
    this.relativeUrl = builder.relativeUrl;
    this.headers = builder.headers;
    this.contentType = builder.contentType;
    this.hasBody = builder.hasBody;
    this.isFormEncoded = builder.isFormEncoded;
    this.isMultipart = builder.isMultipart;
    this.parameterHandlers = builder.parameterHandlers;
  }

传入了网络请求设置好的参数,那么就完成了ServiceMeyhod对象的创建。

6 Retrofit源码解读:serviceMethod域赋值&parameterHander

链接:https://www.jianshu.com/p/6cebe8449761

ServiceMethod loadServiceMethod(Method method) {
    ServiceMethod result;
    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {

这里
        result = new ServiceMethod.Builder(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

要完成ServiceMethod对象的创建,还要调用Builder和Build这两个方法来完成这个创建。

先看一下构建者Builder方法:

public Builder(Retrofit retrofit, Method method) {

首先会对传进来的retrofit和method进行赋值。
      this.retrofit = retrofit;
      this.method = method;


然后调用getAnnotations这个方法,是获取网络请求接口方法接口里的一些注释的。
      this.methodAnnotations = method.getAnnotations();


getGenericParameterType是获取网络请求接口里的参数类型。
      this.parameterTypes = method.getGenericParameterTypes();


getParameterAnnotations是获取网络请求接口方法接口里的一些注解内容的。
      this.parameterAnnotationsArray = method.getParameterAnnotations();
    }

这三个方法调用完之后才能完成ServiceMethod对象的创建。

看一下build方法:

public ServiceMethod build() {


调用createCallAdapter方法,创建网络请求的适配器。
它是根据网络请求接口方法当中的返回值和注解类型,
从Retrofit对象中去获取对应的网络请求适配器的。
是根据返回值和注解类型来判断的。
      callAdapter = createCallAdapter();


然后会根据前面获取到的网络请求适配器的对象,
调用responseType方法返回一个网络请求适配器的类型。
      responseType = callAdapter.responseType();


然后会判断从Retrofit当中获取该网络适配器返回的数据类型,
是否是responseType和OkHttp的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?");
      }


调用createResponseConverter,它是获取网络请求的数据转换器,
就是说他也是根据网络请求接口方法当中的注解类型返回的。
      responseConverter = createResponseConverter();


然后会遍历所有方法的注解,调用parseMethodAnnotation方法 ,就是解析网络请求接口中的注解。
注解的作用就是获取http请求的方法,包括get,post等等。通过这个方法进行解析。
      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).");
        }
      }



获取当前方法参数的数量,调用lenth方法
      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.");
        }


最后调用parseParameter方法去解析方法,参数和注解。
        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);
    }

这就是serviceMethod创建的一些核心的流程。

总结serviceMethod的流程

  1. 网络请求适配器工厂集合和内容转换器工厂集合
    首先,会根据返回值的类型和方法,以及方法的注解,从retrofit网络请求适配器工厂,以及内容转换器工厂,分别获取到我们的网络请求适配器,和内容转换器。

  2. 根据方法的标注对ServiceMethod的域进行赋值
    根据方法的标注对ServiceMethod的对象,以及它的成员变量,进行赋值

  3. 为每个方法的参数的标注进行解析,获得一个ParameterHandler<?>对象
    这个对象,保存有一个request内容转换器,这个转换器,根据我们参数的类型,从retrofit response converter这个内容转换器的集合当中去获取

7 Retrofit源码解读:OkhttpCall和RxJava平台适配

接第5节
在Retrofit类中的create()方法里有个拦截方法叫invoke,invoke拦截方法中最核心的三行代码:

ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);

第一行已经讲完,下面分析第二行和第三行。

第二行,就是通过传入参数构建OkHttpCall对象。

如何去创建OkHttpCall对象:
new OkHttpCall<>(serviceMethod, args)是通过serviceMethod对象,和args这些参数来创建OkHttpCall对象的。

所有的网络请求参数信息的对象:
  private final ServiceMethod<T> serviceMethod;
  
网络请求接口的参数:
  private final Object[] args;

rawCall是实际进行网络访问的类:
  private okhttp3.Call rawCall;

构造方法
OkHttpCall(ServiceMethod<T> serviceMethod, Object[] args) {
    this.serviceMethod = serviceMethod;
    this.args = args;
  }

第三行,会调用serviceMethod中的callAdapter(网络请求适配器)进行不同平台的适配。

adapt方法:

	@Override public <R> Observable<Response<R>> adapt(Call<R> call) {
      Observable<Response<R>> observable = Observable.create(new CallOnSubscribe<>(call));
      if (scheduler != null) {
        return observable.subscribeOn(scheduler);
      }
      return observable;
    }

总结

  1. 动态创建网络请求接口的实例
    在接口中定义网络请求的参数和方法,通过动态代理,拦截接口中定义好的注解、参数和方法

  2. 创建serviceMethod对象
    serviceMethod对象包括所有网络请求的注解、参数等;通过建造者模式,和单例模式创建的

  3. 对serviceMethod对象进行网络请求参数配置
    通过解析网络请求接口方法的参数、返回值、注解类型,就能从retrofit对象中去获取对应的网络请求的Url的地址、网络请求的执行器(用于子线程和主线程切换的执行器)、网络请求的适配器、数据转换器

  4. 对serviceMethod对象加入线程切换的操作
    便于接收到数据后,完成子线程到主线程的切换,把数据交给主线程处理

  5. 最终创建并返回一个OkHttpCall类型的网络请求对象
    有了OkHttpCall这个请求对象,加上我们创建好的request对象,就可以直接去进行网络请求了,同步异步都可以

// 创建 网络请求接口 的实例
    retrofit_interface request = retrofit.create(retrofit_interface.class);

8 Retrofit源码解读:静态代理 & 封装OkHttp & 总结

发动请求的过程

  1. 对网络请求接口的方法中的每个参数,利用ParameterHandler对象进行解析
    然后根据前面创建好的serviceMethod对象,创建一个OkHttp可以使用的request请求对象

  2. 使用OkHttp的request发送网络请求

  3. 对返回的数据使用之前设置的数据转换器(GsonConverterFactory)解析服务器返回给我们的数据

  4. 进行线程切换,从而在主线程处理返回的数据结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值