目录
一,前言
二,使用
三,源码分析
一,前言
retrofit是目前比较流行的网络框架,但它本身并没有网络请求的功能,网络请求的功能是由okhttp来完成的。retrofit只是负责网络请求接口的封装,让我们更加方便的请求网络。
在对retrofit框架进行了解之前,我们需要先了解okhttp,另外retrofit涉及到的设计模式很多,我们主要要了解动态代理模式和适配器模式。
Android-okhttp详解-CSDN博客
Java 代理模式之静态代理与动态代理_java静态代理模式-CSDN博客
Android设计模式--适配器模式_android 适配器模式-CSDN博客
二,使用
在build.gradle配置引用:
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
创建数据类:
data class ArticleBean (val chapterName :String,val link :String
)
创建请求接口:
interface YzTestService {@GET("article/list/0/{name}")fun yzTest(@Path("name") name:String?): Call<List<ArticleBean>>
}
在activity使用:
class CommonActivity : AppCompatActivity() {var url = "https://www.wanandroid.com"override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_common)val retrofit =Retrofit.Builder().baseUrl(url).addConverterFactory(GsonConverterFactory.create()).build()val service =retrofit.create(YzTestService::class.java)val repos:Call<List<ArticleBean>> = service.yzTest("json")repos.enqueue(object :Callback<List<ArticleBean>>{override fun onResponse(call: Call<List<ArticleBean>>, response: Response<List<ArticleBean>>) {Log.d("yz","请求成功:"+response.body().toString())}override fun onFailure(call: Call<List<ArticleBean>>, t: Throwable) {Log.d("yz","请求失败:"+t.toString())}})}
}
三,源码分析
分析源码一般是从使用入手,一般是着眼于最核心的代码。
从使用分析,我们先看repos.enqueue它的源码:
void enqueue(Callback<T> callback);
结果是个抽象方法,所以我们继续往上看它的使用service.yzTest("json"),这个是我们自己创建的,然后接着往上看retrofit.create(YzTestService::class.java)的源码:
public <T> T create(final Class<T> service) {//判断是否接口 不是接口抛出异常validateServiceInterface(service);return (T)//动态代理模式Proxy.newProxyInstance(//第一个参数 任意的类加载器service.getClassLoader(),//第二个参数 传入的service的class对象new Class<?>[] {service},//第三个参数 静态内部类 new InvocationHandler() {private final Platform platform = Platform.get();private final Object[] emptyArgs = new Object[0];//最主要的方法 @Overridepublic @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);}args = args != null ? args : emptyArgs;return platform.isDefaultMethod(method)? platform.invokeDefaultMethod(method, service, proxy, args)// 经过一系列判断 符合条件 走这里: loadServiceMethod(method).invoke(args);}});
}
然后就来看看loadServiceMethod(method)这个方法:
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(this, method)这个方法:
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {//获取方法的注解信息等 创建请求工厂 里面包含请求的url,请求方式,请求参数等等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);
}
如果符合判断条件,则走HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory)
看看这个类:
abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT>
它继承了ServiceMethod这个类,我们在看loadServiceMethod(method).invoke(args)的invoke的方法时,发现它是ServiceMethod的抽象方法,然后我们又看到了HttpServiceMethod这个类继承了ServiceMethod,所以我们在HttpServiceMethod这个类里面找一下invoke这个方法,它就是ServiceMethod的具体实现:
@Override
final @Nullable ReturnT invoke(Object[] args) {Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);return adapt(call, args);
}
然后看它的adapt方法:
protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);
它是HttpServiceMethod的一个抽象方法,所以我们只能倒回去看 OkHttpCall这个类:
final class OkHttpCall<T> implements Call<T>
发现它是继承了Call,就是上面我们说的:
void enqueue(Callback<T> callback);
这个抽象方法。
所以我们看看OkHttpCall这个类里面enqueue这个方法的具体实现:
@Override
public void enqueue(final Callback<T> callback) {Objects.requireNonNull(callback, "callback == null");okhttp3.Call call;Throwable failure;synchronized (this) {if (executed) throw new IllegalStateException("Already executed.");executed = true;call = rawCall;failure = creationFailure;if (call == null && failure == null) {try {//创建okhttp3的Callcall = 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() {@Overridepublic 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}}@Overridepublic 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,并用这个Call对象去请求网络
创建对象的代码为:
call = rawCall = createRawCall();
还有一个主要方法就是:
response = parseResponse(rawResponse);
这行代码主要就是解析返回的数据。具体代码比较简单,就是数据的具体解析。这里就不做具体分析了。
最重要的方法就是:
callback.onResponse(OkHttpCall.this, response);callback.onFailure(OkHttpCall.this, e);
这两个回调就是我们使用的回调。这样整个流程就通了。
看完主线之后,再来看看上面没有看的HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory)这个方法:
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(Retrofit retrofit, Method method, RequestFactory requestFactory) {boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;boolean continuationWantsResponse = false;boolean continuationBodyNullable = false;Annotation[] annotations = method.getAnnotations();Type adapterType;
//判断是否支持kotlin挂起方法if (isKotlinSuspendFunction) {Type[] parameterTypes = method.getGenericParameterTypes();Type responseType =Utils.getParameterLowerBound(0, (ParameterizedType) parameterTypes[parameterTypes.length - 1]);if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {// Unwrap the actual body type from Response<T>.responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);continuationWantsResponse = true;} else {// TODO figure out if type is nullable or not// Metadata metadata = method.getDeclaringClass().getAnnotation(Metadata.class)// Find the entry for method// Determine if return type is nullable or not}adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);} else {adapterType = method.getGenericReturnType();}
// 关键代码 创建CallAdapterCallAdapter<ResponseT, ReturnT> callAdapter =createCallAdapter(retrofit, method, adapterType, annotations);Type responseType = callAdapter.responseType();if (responseType == okhttp3.Response.class) {throw methodError(method,"'"+ getRawType(responseType).getName()+ "' is not a valid response body type. Did you mean ResponseBody?");}if (responseType == Response.class) {throw methodError(method, "Response must include generic type (e.g., Response<String>)");}// TODO support Unit for Kotlin?if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {throw methodError(method, "HEAD method must use Void as response type.");}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);}
}
从上面的代码中我们提取出一个关键代码:createCallAdapter,来看看它的源码:
private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) {try {//noinspection uncheckedreturn (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);}
}
接着往下看retrofit.callAdapter:
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {return nextCallAdapter(null, returnType, annotations);
}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;}}StringBuilder builder =new StringBuilder("Could not locate call adapter for ").append(returnType).append(".\n");if (skipPast != null) {builder.append(" Skipped:");for (int i = 0; i < start; i++) {builder.append("\n * ").append(callAdapterFactories.get(i).getClass().getName());}builder.append('\n');}builder.append(" Tried:");for (int i = start, count = callAdapterFactories.size(); i < count; i++) {builder.append("\n * ").append(callAdapterFactories.get(i).getClass().getName());}throw new IllegalArgumentException(builder.toString());
}
这里面没有什么有用的代码 关键就是callAdapterFactories.get(i).get(returnType, annotations, this);这个方法,我们先看下callAdapterFactories是什么:
final List<CallAdapter.Factory> callAdapterFactories;
再看下它在哪里赋值的:
public Retrofit build() {if (baseUrl == null) {throw new IllegalStateException("Base URL required.");}okhttp3.Call.Factory callFactory = this.callFactory;if (callFactory == null) {callFactory = new OkHttpClient();}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));// Make a defensive copy of the converters.List<Converter.Factory> converterFactories =new ArrayList<>(1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());// Add the built-in converter factory first. This prevents overriding its behavior but also// ensures correct behavior when using converters that consume all types.converterFactories.add(new BuiltInConverters());converterFactories.addAll(this.converterFactories);converterFactories.addAll(platform.defaultConverterFactories());return new Retrofit(callFactory,baseUrl,unmodifiableList(converterFactories),unmodifiableList(callAdapterFactories),callbackExecutor,validateEagerly);
}
这个就是在我们使用的时候,调用Retrofit.build方法的时候,赋值的。
具体看下它的赋值内容:
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));
因为我们是android平台 所以我们直接查看platform.defaultCallbackExecutor()找android平台就能看到它的具体实现:
@Override
public Executor defaultCallbackExecutor() {return new MainThreadExecutor();
}
static final class MainThreadExecutor implements Executor {private final Handler handler = new Handler(Looper.getMainLooper());@Overridepublic void execute(Runnable r) {handler.post(r);}
}
这个就是切换到了主线程。
然后我们回到上面看看callAdapterFactories.get(i).get(returnType, annotations, this);的方法:
@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<?>>() {@Overridepublic Type responseType() {return responseType;}@Overridepublic Call<Object> adapt(Call<Object> call) {return executor == null ? call : new ExecutorCallbackCall<>(executor, call);}};
}
然后我们就发现了adapt方法,我们回到前面的代码:
@Override
final @Nullable ReturnT invoke(Object[] args) {Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);return adapt(call, args);
}
这个里面的adapt就是上面的adapt,它把OKHttpcall又包了一层,具体看看怎么包装的:
static final class ExecutorCallbackCall<T> implements Call<T> {final Executor callbackExecutor;//传入的android平台的executor 用于切换主线程final Call<T> delegate; //OKHttpCallExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {this.callbackExecutor = callbackExecutor;this.delegate = delegate;}@Overridepublic void enqueue(final Callback<T> callback) {Objects.requireNonNull(callback, "callback == null");delegate.enqueue(new Callback<T>() {@Overridepublic 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.//调用者传入的callbackcallback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));} else {//调用者传入的callbackcallback.onResponse(ExecutorCallbackCall.this, response);}});}@Overridepublic void onFailure(Call<T> call, final Throwable t) {callbackExecutor.execute(() -> callback.onFailure(ExecutorCallbackCall.this, t));}});}@Overridepublic boolean isExecuted() {return delegate.isExecuted();}@Overridepublic Response<T> execute() throws IOException {return delegate.execute();}@Overridepublic void cancel() {delegate.cancel();}@Overridepublic boolean isCanceled() {return delegate.isCanceled();}@SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.@Overridepublic Call<T> clone() {return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());}@Overridepublic Request request() {return delegate.request();}@Overridepublic Timeout timeout() {return delegate.timeout();}
}
这样就在内部结果返回时自动切换到了主线程,避免了用户自己切换线程的麻烦。