Retrofit

一、Retrofit请求流程

1、创建网络请求接口,定义请求数据方法

定义请求网络数据的方法,用注解的方式声明网络请求的方法和参数。这些方法和参数会在RequestFactory的build方法中去解析,将解析获得的数据会存储到RequestFactory的对象中。这些数据用来创建Okhttp的request请求。

2、创建retrofit

1)用建造者模式创建Retrofit对象,建造者模式的作用是将复杂对象的构建与表示分离,帮助用户在不需要了解创建对象细节的情况下,依然可以创建复杂的对象。

2)在Retrofit的Builder()方法中,判断当前的平台是否Android,并创建AndroidPlatform。里面有静态内部类MainThreadExecutor,通过Looper.getMainLooper()获取主线程的handler用于线程切换。

3)添加baseUr,对baseUrl进行非空判断和以/结尾的判断,然后解析baseUrl为HttpUrl类。HttpUrl的作用是解析网络请求地址。scheme、host等。

4)添加数据解析器addConverterFactory,我们用GsonConverterFactory。

5)添加call适配器。作用是:可以将默认的网络请求执行器OkHttpCall转换成适合不同平台使用的网络请求执行器。比如:默认是DefaultCallAdapterFactory,这样会生成网络请求执行器ExecutorCallbackCall。如果我们想使用Rxjava切换线程,就需要调用addCallAdapterFactory(RxJava2CallAdapterFactory.create())

6) 添加okHttpClient:用来创建网络请求RealCall。

7)最后调用build方法,将Retrofit的所有成员变量配置完成,最后返回retrofit对象。

3、创建网络请求接口的动态代理类并获取网络请求Call

1)通过proxy的newProxyInstance创建网络请求接口的动态代理类

2)当调用数据请求方法的时候,会被动态代理类拦截调用自身的InvocationHandler的invoke()方法。invoke方法会传入三个参数,Object proxy:(代理对象)、Method method(调用的getData()),Object… args(方法的参数,即getData(*)中的参数)。

3)在invoke方法中会创建HttpServiceMethod对象,ServiceMethod对象创建过程中会解析网络请求方法上的注解和参数注解,比如POST、GET、Path、Query、Field、Body等,

4)调用ServiceMethod的invoke方法,创建OkHttpCall,然后调用网络请求适配器CallAdapter的adapt方法进行适配,Android默认的是ExecutorCallbackCall,若设置了RxJavaCallAdapterFactory,返回的则是Observable。

4、调用enqueue执行异步请求

默认使用ExecutorCallbackCall,执行enqueue方法。它的内部实现还是OkHttpCall。

1)通过requestFactory创建网络request。

2)okHttpClient创建RealCall

3)调用RealCall的enqueue方法,执行网络请求获取response。

4)通过responseConverter对rawResponse进行解析,然后调用callBack回调到ExecutorCallbackCall的onResponse。

5)在ExecutorCallbackCall中会调用callbackExecutor的execute方法。会获取我们的主线程handler,进行线程切换。

二、创建网络请求接口,定义请求数据的方法

作用:

1)定义请求数据的方法。

2)用注解的方式声明了网络请求的参数和方法。这些方法和参数会在RequestFactory的build方法中去解析,将解析获得的数据会存储到RequestFactory的对象中。具体看❌❌❌

interface RetrofitApi {
    @GET("users/{user}/repos")
    fun getData(@Path("user") user: String): Call<User>
}

三、创建Retrofit

val okhttpClient = OkHttpClient.Builder().build()
var retrofit = Retrofit.Builder()
    .baseUrl("https://columbus.iboohee.com/")
    .addConverterFactory(GsonConverterFactory.create()) //设置数据转换器
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())//支持rxjava平台
    .client(okhttpClient)
    .build()

(1)Retrofit.Builder()方法

解析:依次调用Retrofit.Builder()->Platform.get()->findPlatform(),里面主要创建了MainThreadExecutor,里面通过Looper.getMainLooper()创建了主线程的Handler,用于子线程切换到主线程。

//1、Retrofit的Builder内部类
public Builder() {
  this(Platform.get());
}
//2、调用Platform的get方法,通过单例模式创建PLATFORM,调用findPlatform方法。
class Platform {
  private static final Platform PLATFORM = findPlatform();
  static Platform get() {
    return PLATFORM;
  }
 //3、判断是否是Dalvik虚拟机,创建AndroidPlatform
private static Platform findPlatform() {
  return "Dalvik".equals(System.getProperty("java.vm.name"))
      ? new Android() //
      : new Platform(true);
}
//4、在Android中,defaultCallbackExecutor会在retrofit的创建过程中被调用,返回MainThreadExecutor。在MainThreadExecutor中会通过Looper.getMainLooper()创建主线程的Handler用于线程切换。
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);
    }
  }
}
}

(2) 添加baseUrl

解析:添加baseUrl逻辑很简单,对baseUrl进行非空判断,然后解析baseUrl为HttpUrl类。HttpUrl的作用是解析网络请求地址。scheme(https)、host(www.google.com)等。

public Builder baseUrl(String baseUrl) {
  //1、对baseUrl进行空判断
  Objects.requireNonNull(baseUrl, "baseUrl == null");
   //2、解析baseUrl为HttpUrl,解析网络请求地址。
  return baseUrl(HttpUrl.get(baseUrl));
}

(3) addConverterFactory

解析:创建了一个含有Gson实例的GsonConverterFactory,然后添加到converterFactories集合中。

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

(4) addCallAdapterFactory

解析:添加call适配器到callAdapterFactories集合中。适配器的作用是:可以将默认的网络请求执行器OkHttpCall转换成适合不同平台使用的网络请求执行器。

在Retrofit中提供了三种CallAdapterFactory: CompletableFutureCallAdapterFactory(仅在CompletableFuture可用时(Java 8 + / Android API 24+)添加)、DefaultCallAdapterFactory、RxJava2CallAdapterFactory

默认是DefaultCallAdapterFactory,这样会生成默认的网络请求执行器(OkHttpCall),OkHttpCall通过ExecutorCallbackCall切换线程。如果我们想使用Rxjava切换线程,就需要调用addCallAdapterFactory(RxJava2CallAdapterFactory.create()),使用RxJava2CallAdapterFactory将OkHttpCall转换成Observable

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

(5) build过程

解析:

设置网络请求工厂(callFactory),默认使用OkHttpClient;

设置回调方法执行器callbackExecutor,用于线程切换。

设置网络请求适配器工厂的集合callAdapterFactories,默认DefaultCallAdapterFactory

设置数据转换器工厂的集合(converterFactories)

public Retrofit build() {
  //1、判断baseUrl是否为空
  if (baseUrl == null) {
    throw new IllegalStateException("Base URL required.");
  }
  //2、设置callFactory,默认是OkHttpClient
  okhttp3.Call.Factory callFactory = this.callFactory;
  if (callFactory == null) {
    callFactory = new OkHttpClient();
  }
  //3、设置MainThreadExecutor,用于线程切换。默认是AndroidPlatform的defaultCallbackExecutor。见Retrofit.Builder()方法。
  Executor callbackExecutor = this.callbackExecutor;
  if (callbackExecutor == null) {
    callbackExecutor = platform.defaultCallbackExecutor();
  }
  //4、设置call适配器集合,对网络请求执行器call进行适配转换以适应不同平台。
  List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
  
   //5、添加默认的DefaultCallAdapterFactory,见Platform。作用是对call转换成
  ExecutorCallbackCall
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
   //6、添加数据转换器
  List<Converter.Factory> converterFactories =
      new ArrayList<>(
          1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
  converterFactories.add(new BuiltInConverters());
  converterFactories.addAll(this.converterFactories);
  converterFactories.addAll(platform.defaultConverterFactories());
    //7、调用retrofit的构造方法,对成员变量进行赋值。完成了retrofit的实例化。
  return new Retrofit(
      callFactory,
      baseUrl,
      unmodifiableList(converterFactories),
      unmodifiableList(callAdapterFactories),
      callbackExecutor,
      validateEagerly);
}

四、创建网络请求接口的动态代理类并获取网络请求Call

val api = retrofit.create(RetrofitApi::class.java)
val call = api.getData()

(1)retrofit.create

解析:通过动态代理模式proxy的newProxyInstance创建网络请求接口的动态代理类,当调用请求数据的方法的时候,会被动态代理类拦截调用自身的InvocationHandler的invoke()方法。在invoke方法中会调用loadServiceMethod(method).invoke(args)方法。

public <T> T create(final Class<T> service) {
//1、判断service是否是接口,后判断是否validateEagerly,调用loadServiceMethod,将HttpServiceMethod对象添加到serviceMethodCache(ConcurrentHashMap中)
  validateServiceInterface(service);
  //2、通过动态代理模式Proxy.newProxyInstance创建网络请求接口的动态代理类。
 有三个参数: Object proxy:代理对象、Method method方法、Object... args(方法的参数)
  return (T) Proxy.newProxyInstance(service.getClassLoader(),
        new Class<?>[] {service},new InvocationHandler() {
            、、、
              return loadServiceMethod(method).invoke(args);
            }
          });
}
//3、当api.getData()调用请求数据的方法时,会被动态代理类拦截调用自身的InvocationHandler的invoke方法。在invoke方法中会调用loadServiceMethod(method).invoke(args)方法

(2)loadServiceMethod

解析:

//1、调用loadServiceMethod方法,先从serviceMethodCache中获取,如果为空需要创建。
ServiceMethod<?> loadServiceMethod(Method method) {
  ServiceMethod<?> result = serviceMethodCache.get(method);
  if (result != null) return result;
  synchronized (serviceMethodCache) {
    result = serviceMethodCache.get(method);
    if (result == null) {
   //2、创建ServiceMethod,见3
      result = ServiceMethod.parseAnnotations(this, method);
      serviceMethodCache.put(method, result);
    }
  }
  return result;
}
 //3、解析注解,创建ServiceMethod。
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
 //4、通过RequestFactory解析数据请求方法上的注解和参数注解。并赋值给RequestFactory的成员变量,见步骤6
  RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
   //获取方法上的返回类型
  Type returnType = method.getGenericReturnType();
         、、、
//5、通过retrofit、method、requestFactory创建HttpServiceMethod。返回call
  return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
//RequestFactory
final class RequestFactory {
//6、对RequestFactory的成员变量进行初始化,主要包括method、baseUrl、headers
、contentType、hasBody等
  static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
    return new Builder(retrofit, method).build();
  }
 //7、调用build方法
RequestFactory build() {
//8、解析方法注解,比如:DELETE、GET、HEAD、PATCH、POST、PUT、OPTIONS、HTTP、Multipart、FormUrlEncoded
  for (Annotation annotation : methodAnnotations) {
    parseMethodAnnotation(annotation);
  }
  、、、
  //9、通过ParameterHandler解析参数注解,参数注解:Url、Path、Query、QueryName、QueryMap、Header、HeaderMap、Field、FieldMap、Part、PartMap、Body、Tag
  
  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);
}
  //10、返回RequestFactory对象
return new RequestFactory(this);
 }
}

(3)invoke方法

创建OkHttpCall,然后调用adapt()方法,进行call转换。Android默认的是DefaultCallAdapterFactory的ExecutorCallbackCall;若设置了RxJavaCallAdapterFactory,返回的则是Observable<>。

Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
//调用 callAdapter.adapt(call);可以看DefaultCallAdapterFactory这个类

五、执行异步请求

解析:

1、在上一步创建call方法中,我们获得的call是DefaultCallAdapterFactory的ExecutorCallbackCall,然后执行enqueu方法。内部其实还是调用的OkHttpCall的enqueue方法,在ExecutorCallbackCall中进行线程切换和response的成功失败方法的回调。

2、执行OkHttpCall的enqueue。里面主要分三步

1)创建真实的请求RealCall,就是我们在okhttp中执行网络的RealCall。

RealCall的创建:callFactory.newCall(requestFactory.create(args));callFactory是我们创建的OkHttpClient,requestFactory中存储我们的请求方法和请求参数。

2)调用RealCall的enqueue方法,执行网络请求获取response。

3)通过responseConverter对rawResponse进行解析,然后调用callBack回调到ExecutorCallbackCall的onResponse。

4)在ExecutorCallbackCall中会调用callbackExecutor的execute方法。会获取我们的主线程handler,进行线程切换。

DefaultCallAdapterFactory的ExecutorCallbackCall的enqueue方法
@Override
public void enqueue(final Callback<T> callback) {
  Objects.requireNonNull(callback, "callback == null");
  //1、delegate实际上是okHttpCall
  delegate.enqueue(
      new Callback<T>() {
        @Override
        public void onResponse(Call<T> call, final Response<T> response) {
         //2、在这里进行线程切换,见步骤7
          callbackExecutor.execute(
             、、、
             callback.onResponse(ExecutorCallbackCall.this, response);
             );
        }
        @Override
        public void onFailure(Call<T> call, final Throwable t) {
          callbackExecutor.execute(() -> callback.onFailure(ExecutorCallbackCall.this, t));
        }
      });
}
OkHttpCall的enqueue方法代码简化,伪代码
public void enqueue(final Callback<T> callback) {
 //3、创建realCall
  call = rawCall = createRawCall();
 //4、此时就是OkHttp的网络请求
  call.enqueue( new okhttp3.Callback() {
        @Override
        public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
          Response<T> response;
           //5、解析数据
           response = parseResponse(rawResponse);
           //6、数据返回给callbackExecutor见步骤2
           callback.onResponse(OkHttpCall.this, response);
          、、、
}
//7、通过Looper.getMainLooper()获取主线程handler进行线程切换
static final class MainThreadExecutor implements Executor {
  private final Handler handler = new Handler(Looper.getMainLooper());
  @Override
  public void execute(Runnable r) {
    handler.post(r);
  }
}

六、Retrofit的使用

1、post请求传递数组json

{
"ids": ["8257", "8256", "8255"],
"checked": false
}

(1)请求代码:

// 创建json对象
JSONObject jsonObject = new JSONObject();
// 1个数组参数
JSONArray jsonArray = new JSONArray();
for (String tag : tags) {
jsonArray.put(tag);
}
jsonObject.put("tags", jsonArray);
jsonObject.put("token", token);
String data = jsonObject.toString();
Route.ModulesList modulesList = retrofit.create(Route.ModulesList.class);
RequestBody requestBody = RequestBody.create(okhttp3.MediaType.parse("application/json;charset=UTF-8"), data);
getModulesList(requestBody)
 
public interface ModulesList {
// @FormUrlEncoded // 使用@Body时,就不要使用@FormUrlEncoded,否则会报错!
@POST("cms/modules")
Call<ModuleBean> getModulesList(@Body RequestBody data);
   
 或者直接传递对象,requestBean是对象里面定义了我们传递的参数
 Call<ModuleBean> getModulesList(@Body requestBean data);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值