Retrofit基本使用以及源码解读

https://square.github.io/retrofit/

主要讲:

  • retrofit基本使用介绍
  • retrofit的常用注解的使用方法
  • retrofit主流程讲解
  • retrofit关键点面试点讲解

知识点:

  • 上传图片:单个 、 多个
  • 图文混传
  • 下载文件要注意的点
  • 涉及到的技术:注解 + 泛型 + 动态代理 (retrofit2 经典,超级多的设计模式)
  • retrofit 请求 -> 返回结果,默认 一次性返回到内存,如果是请求文件就可能会导致OOM,这时需要用到 Streaming注解,Streaming 表示响应体的数据用流的方式返回,适用于返回的数据比较大的情况,该注解在下载大文件时特别有用

Retrofit基础资料

https://pan.baidu.com/s/1bMjOFZPQJVvHhj6Oy63DPg

Retrofit是什么

官网介绍是:A type-safe HTTP client for Android and Java,是一个 RESTful 的 HTTP 网络请求框架的封装,但网络请求不是Retrofit来完成的,它只是封装了请求参数、Header、Url、返回结果处理等信息,而请求是由OkHttp3来完成的。

入门

  1. 导包
//网络请求相关 
implementation "com.squareup.retrofit2:retrofit:$rootProject.retrofitVersion"
implementation "com.squareup.retrofit2:retrofit- mock:$rootProject.retrofitVersion" 
implementation "com.squareup.retrofit2:converter- gson:$rootProject.retrofitVersion" 
implementation 'com.squareup.okhttp3:logging-interceptor:3.5.0' 
implementation "com.squareup.retrofit2:converter- scalars:$rootProject.retrofitVersion" 
implementation "com.squareup.retrofit2:adapter- rxjava2:$rootProject.retrofitVersion" 
implementation "com.squareup.retrofit2:converter- gson:$rootProject.retrofitVersion"
  1. 定义一个HTTP API接口类
interface WanAndroidApi { 
	@GET("project/tree/json") 
	Call<ProjectBean> getProject(); 
}
  1. 使用Retrofit类生成WanAndroidApi的接口实现
Retrofit retrofit = new Retrofit.Builder()//建造者模式 
.baseUrl("https://www.wanandroid.com/") 
.addConverterFactory(GsonConverterFactory.create()) 
.build(); 
WanAndroidApi wanAndroidApi = retrofit.create(WanAndroidApi.class);// 代理实例
  1. 发送HTTP请求,返回Response可以同步或者异步处理
Call<ProjectBean> call = wanAndroidApi.getProject();//获取具体的某个业务接口
//同步请求 
Response<ProjectBean> response = call.execute(); 
ProjectBean projectBean = response.body(); 
//异步请求 
call.enqueue(new Callback<ProjectBean>() { 
	@Override 
	public void onResponse(final Call<ProjectBean> call, final Response<ProjectBean> response) { 
		Log.i("Zero","response: " + response.body()); 
	}
	
	@Override 
	public void onFailure(final Call<ProjectBean> call, final Throwable t){
	
	} 
});

注解分类解析

请求方法类

标记类

参数类

原理分析

详见:Retrofit原理流程图及源码分析

关键类功能说明

Retrofit

Retrofit提供的子系统

  1. serviceMethodCache(自定义的接口映射对象集合)
  2. baseUrl(请求地址)
  3. callFactory(默认为OKHttpCall)
  4. converterFactories(数据解析器工厂集合)
  5. callAdapterFactories(Call适配器工厂集合)
  6. callbackExecutor(回调执行,Android平台默认为MainThreadExecutor)

使用Builder模型构建(把对象依赖的零件创建、零件的组装封装起来;以使客户很方便的获取一个复杂对象;)

Platform

Retrofit中用来管理多平台的方法,支持Android、Java8。通过findPlatform获取对应的平台,同时也初始化了defaultCallAdapterFactory工厂。

ServiceMethod

接口映射的网络请求对象,通过动态代理,将自定义接口的标注转换为该对象,将标注及参数生成OkHttp所需的Request对象。Retrofit的create通过动态代理拦截,将每一个自定义接口转换成为一个ServiceMethod对象,并通过通过serviceMethodCache进行缓存。

ServiceMethod描述的是解析之后的请求方法,请求方法的注解、参数、返回类型等解析完了之后都封装在ServiceMethod。

Call

Retrofit定义的网络请求接口,包含execute、enqueue等方法

OkHttpCall

OkHttp的Call实现,通过createRawCall得到真正的 okhttp3.Call对象,用于进行实际的网络请求

CallAdapter.Factory

CallAdapter的静态工厂,包含get的抽象方法,用于生产CallAdapter对象

ExecutorCallAdapterFactory

Android平台默认的CallAdapter工厂,get方法使用匿名内部类实现CallAdapter,返回ExecutorCallbackCall,实现了Call

ExecutorCallbackCall

采用静态代理设计,delegate实际为OkHttpCall,使用callbackExecutor实现回调在主线程中执行

RxJavaCallAdapterFactory

Rxjava平台的CallAdapter工厂,get方法返回RxJavaCallAdapter对象

RxJavaCallAdapter

Rxjava平台的设配器,返回observable对象

Converter.Factory

数据解析器工厂,用于生产Converter实例

GsonConverterFactory

数据解析工厂实例,返回了GsonResponseBodyConverter数据解析器

GsonResponseBodyConverter

Gson的数据解析器,将服务端返回的json对象转换成对应的java模型

Response

Retrofit网络请求响应的Response

关键的几个流程

  1. Retrofit 如何将定义的interface转换成网络请求?
  2. Retrofit的Converter机制是如何实现?
  3. Retrofit的CallAdapter机制是如何实现?

Converter种类

CallAdapter种类

如何自定义一个Converter及CallAdapter?

Retrofit中的设计模式

1. 建造者模式

Retrofit对象的创建、ServiceMethod对象创建都使用Build模式,将复杂对象的创建和表示分离,调用者不需要知道复杂的创建过程,使用Build的相关方法进行配置创建对象。

2. 外观模式

Retrofit对外提供了统一的调度,屏蔽了内部的实现,使得使用该网络库简单便捷。
门面模式: 提供一个统一的接口去访问多个子系统的多个不同的接口,它为子系统中的一组接口提供一个统一的高层接口,使子系统更容易使用。

3. 动态代理模式

通过动态代理的方式,当调用Retrofit的create()方法时,会进行动态代理监听。当执行具体的接口方法时,会回调InvocationHandler。通过反射解析method的标注及参数,生成ServiceMethod对象。

4. 静态代理模式

Android平台默认的适配器ExecutorCallbackCall,采用静态代理的模式。具体的实现delegate为OkHttpCall。

5. 工厂模式

Converter及CallAdapter的创建都采用了工厂模式进行创建。

6. 适配器模式

CallAdapter的adapt采用了适配器模式,使得interface的返回对象可以动态扩展,增强了灵活性。

OkHttp, Retrofit, Volley应该如何选择?

Retrofit原理流程图及源码分析

在这里插入图片描述
Retrofit原理整体可以分为三大部分:
第一部分:创建retrofit对象,通过retrofit对象获得接口的动态代理对象
第二部分:调用动态代理对象的接口方法时获得retrofit的Call对象
第三部分:调用Call.execute或者Call.enqueue执行网络请求,将请求结果转换为Response对象

1.获得接口的动态代理对象

通过动态代理来实现。

先生成retrofit对象:

//Retrofit.java

public Retrofit build() {

	...
	
     okhttp3.Call.Factory callFactory = this.callFactory;
     if (callFactory == null) {
     	callFactory = new OkHttpClient();//创建OkHttpClient对象执行http请求,OkHttpClient就是okhttp3.Call.Factory
     }

	  //callbackExecutor 用于将响应结果发送到UI主线程
	  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));


}


DefaultCallAdapterFactory创建的是ExecutorCallbackCall对象,ExecutorCallbackCall封装了Call请求和回调处理对象。

传递给retrofit对象的是接口,如何获得接口的实例对象?

看下retrofit.create()方法:

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 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,返回的是实现了service接口的代理实例对象。

2.调用动态代理对象的接口方法时获得retrofit的Call对象

当调用代理实例对象实现的接口方法(比如例子中的wanAndroidApi.getProject()方法)时最终都会调用invoke方法:

          @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);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
          }

看下loadServiceMethod方法:

//Retrofit.java

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解析注解时会用到大量的反射调用,非常耗性能,使用缓存来缓存解析的结果,解析过了就不需要再次解析了,直接从缓存中获取。

用到反射时就要考虑使用缓存进行缓存结果,提高性能。Android源码中很多地方都这么用,比如:LayoutInflater的createViewFromTag()方法根据xml解析view时也做了缓存。

ServiceMethod.parseAnnotations方法是真正解析方法上的注解:

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

调用RequestFactory.parseAnnotations方法解析请求的参数,封装在RequestFactory中:

//RequestFactory.java

final class RequestFactory {
  static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
    return new Builder(retrofit, method).build();
  }

  private final Method method;//请求的方法
  private final HttpUrl baseUrl;//请求的url
  final String httpMethod;//时get请求还是post请求
  private final @Nullable String relativeUrl;//相对url
  private final @Nullable Headers headers;//请求头
  private final @Nullable MediaType contentType;
  private final boolean hasBody;
  private final boolean isFormEncoded;
  private final boolean isMultipart;
  private final ParameterHandler<?>[] parameterHandlers;//请求参数
  final boolean isKotlinSuspendFunction;

...

RequestFactory 也是建造者模式:

//RequestFactory.java

    Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      this.method = method;
      this.methodAnnotations = method.getAnnotations();//获取方法上的所有注解
      this.parameterTypes = method.getGenericParameterTypes();//获取方法上的泛型类型
      this.parameterAnnotationsArray = method.getParameterAnnotations();
    }

获取到注解后进行解析:

//RequestFactory.java

    RequestFactory build() {
      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }

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

这样就将接口的方法上的注解封装成http请求的参数。

回到ServiceMethod.parseAnnotations方法,解析完请求参数后对返回类型进行判断:

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

RequestFactory.parseAnnotations进行解析完请求参数后再次调用HttpServiceMethod.parseAnnotations进行第二次解析(HttpServiceMethod是ServiceMethod的子类):

static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {

	...
	CallAdapter<ResponseT, ReturnT> callAdapter =
        createCallAdapter(retrofit, method, adapterType, annotations);
    Type responseType = callAdapter.responseType();
	...


}

为什么要调用HttpServiceMethod.parseAnnotations进行第二次解析?
CallAdapter就是根据方法的返回值类型进行创建的。
如果返回值类型是默认的Call,比如:

interface WanAndroidApi {
    fun getProject(): Call<ProjectBean>
	
	...
}

那么返回的就是DefaultCallAdapterFactory#ExecutorCallbackCall这种类型的Call。

如果返回类型是RxJava的Observable类型,比如:

public interface WangAndroidApi {

    // 总数据
    @GET("project/tree/json")
    Observable<ProjectBean> getProject();
    	
    ...
}

那么返回的就是RxJava2CallAdapterFactory创建的RxJava2CallAdapter创建的Observable:

//RxJava2CallAdapter.java

@Override 
public Object adapt(Call<R> call) {
    Observable<Response<R>> responseObservable = isAsync
        ? new CallEnqueueObservable<>(call)
        : new CallExecuteObservable<>(call);

    Observable<?> observable;
    if (isResult) {
    	observable = new ResultObservable<>(responseObservable);
    } else if (isBody) {
    	observable = new BodyObservable<>(responseObservable);
    } else {
    	observable = responseObservable;
    }
	
	...
}

如何实现的?看下createCallAdapter方法:

  private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
      Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) {
    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);
    }
  }

最终会调用nextCallAdapter方法获取对应的CallAdapter.Factory

//Retrofit.java

  public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) {
    Objects.requireNonNull(returnType, "returnType == null");
    Objects.requireNonNull(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;
      }
    }

遍历callAdapterFactories根据returnType和annotations找到CallAdapter.Factory,然后根据CallAdapter.Factory获取CallAdapter,而这些callAdapterFactories是在Retrofit创建的时候初始化的,默认添加的就是DefaultCallAdapterFactory:

//Retrofit.java

public Retrofit build() {

	...
      		   callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

}

各种类型的 CallAdapterFactory就是为了创建 CallAdapter而存在的。

loadServiceMethod方法解析完之后就调用invoke方法:

          @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);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
          }
  @Override final @Nullable ReturnT invoke(Object[] args) {
    Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
    return adapt(call, args);
  }
    @Override 
    protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
      return callAdapter.adapt(call);
    }
//DefaultCallAdapterFactory.java

      @Override public Call<Object> adapt(Call<Object> call) {
        return executor == null
            ? call
            : new ExecutorCallbackCall<>(executor, call);
      }

生成一个ExecutorCallbackCall对象,即最终得到了Call对象,这里用到的是适配器模式。

总结:
1.调用ServiceMethod.parseAnnotations进行解析请求方法的参数,封装在RequestFactory中。
2.调用HttpServiceMethod.parseAnnotations进行解析请求方法的返回类型,得到retrofit的Call对象。

3.调用Call.execute或者Call.enqueue执行网络请求,将请求结果转换为Response对象

得到retrofit的Call对象后就是执行网络请求,将请求结果转换为Response对象,然后返回。下面进行分析。

默认的Call对象是DefaultCallAdapterFactory#ExecutorCallbackCall,看下源码:

//DefaultCallAdapterFactory.java

	 ...
	
	static final class ExecutorCallbackCall<T> implements Call<T> {
	    final Executor callbackExecutor;
	    final Call<T> delegate;
	    ...

	}

有两个成员变量,delegate和callbackExecutor
这里用的高了静态代理模式,这个delegate就是创建的OkHttpCall对象:

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

也就是说最终是通过OkHttpCall执行网络请求的。

callbackExecutor就是http请求结果的处理器。

所以当调用ExecutorCallbackCall的enqueue方法时,最终调用的是OkHttpCall的enqueue方法执行真正的网络请求:

  @Override public void enqueue(final Callback<T> callback) {
    Objects.requireNonNull(callback, "callback == null");

    okhttp3.Call call;//okhttp3的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) {
          throwIfFatal(e);
          callFailure(e);
          return;
        }

        try {
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          throwIfFatal(t);
          t.printStackTrace(); // TODO this is not great
        }
      }

      @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) {
          throwIfFatal(t);
          t.printStackTrace(); // TODO this is not great
        }
      }
    });
  }

调用okhttp3的Call对象执行真正的网络请求。获取到okhttp3返回的结果rawResponse后,调用parseResponse方法将结果转化为retrofit的Response,转换时使用的是

//OkHttpCall.java

    try {
      T body = responseConverter.convert(catchingBody);
      return Response.success(body, rawResponse);
    } 

responseConverter是从retrofit初始化时的converterFactories中获取的,比如我们初始化retrofit的时候添加了GsonConverterFactory:

        val retrofit = Retrofit.Builder()
            //Retrofit2的baseUrl必须以 /(斜杆)结束,否则会抛出一个IllegalArgumentException
            .baseUrl("https://www.wanandroid.com/")
            .addConverterFactory(GsonConverterFactory.create())//添加json解析器,因为要用到json解析
            .build()

那么解析响应的时候就用到GsonConverterFactory。然后把结果封装在retrofit的Response中,返回给最初调用的地方:

        getProjectCall.enqueue(object : Callback<ProjectBean> {
            override fun onFailure(call: Call<ProjectBean>, t: Throwable) {
                Log.i(TAG, "错误:${t.message}")
            }

            override fun onResponse(call: Call<ProjectBean>, response: Response<ProjectBean>) {
                Log.i(TAG, "成功: ${response.body()}")
            }

        })

总结:

  • retrofit底层使用okhttp执行网络请求的优点:okhttp的请求速度快,连接池复用机制,okio效率高
  • 由以上源码分析可知,okhttp的Call对象并不是在创建Retrofit对象时创建的,而是在执行retrofit的Call对象的execute或者enqueue方法时创建的。
  • okhttp与HttpUrlConnection和HttpClient一样,都是执行http请求的,但是okhttp性能好,速度快,效率高。

常见面试题

Retrofit的Call和Okhttp的Call的区别

//retrofit2.Call.java
public interface Call<T> extends Cloneable {
	...
}

Retrofit的Call是对请求方法的封装。

//okhttp3.Call.java
public interface Call extends Cloneable {
	...
}

Okhttp的Call是用于真正的执行网络请求。

Retrofit的Call调用exexute或则enqueue时会创建Okhttp的Call对象执行网络请求。

Retrofit用到哪些设计模式

重点要阐述动态代理模式和反射。

Http Headers

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值