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