Android-retrofit源码解析

news/2025/2/7 9:36:58/

目录

一,前言

二,使用

三,源码分析


一,前言

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

这样就在内部结果返回时自动切换到了主线程,避免了用户自己切换线程的麻烦。


http://www.ppmy.cn/news/1570039.html

相关文章

selenium记录Spiderbuf例题C01

防止自己遗忘&#xff0c;故作此为记录。 步骤&#xff1a; &#xff08;1&#xff09;进入例题&#xff0c;找到需要点击的元素。 可得button xpath&#xff1a; click_xpath: str r//li/a[title"mnist"] WebDriverWait(driver, 10).until(expected_conditions.…

将音频mp3文件添加背景音乐

你可以使用 Python 的 pydub 库来合成两个音频文件&#xff0c;并调整背景音乐的音量&#xff0c;使朗诵的声音更强。以下是实现的 Python 代码&#xff1a; 步骤 读取朗诵音频文件&#xff08;speech.mp3&#xff09;。读取背景音乐文件&#xff08;background.mp3&#xff…

项目顺利交付,几个关键阶段

年前离放假还有10天的时候&#xff0c;来了一个应急项目&#xff0c; 需要在放假前一天完成一个演示版本的项目&#xff0c;过年期间给甲方领导看。 本想的最后几天摸摸鱼&#xff0c;这么一来&#xff0c;非但摸鱼不了&#xff0c;还得加班。 还在虽然累&#xff0c;但也是…

LiteDB 使用教程

一、引言 在软件开发中&#xff0c;数据存储和管理是至关重要的一环。对于小型项目或者对性能和便捷性有较高要求的场景&#xff0c;传统的大型数据库可能显得过于笨重。而 LiteDB 作为一款轻量级的嵌入式 NoSQL 数据库&#xff0c;为开发者提供了一个简洁、高效的解决方案。它…

深度学习|表示学习|卷积神经网络|NIN 相比普通 CNN|17

如是我闻&#xff1a; Network in Network (NIN) 是 2014 年由 Min Lin 等人 提出的一个改进 CNN 结构的模型。它的核心思想是&#xff1a;用小型的多层感知机&#xff08;MLP&#xff0c;Multi-Layer Perceptron&#xff09;替代传统 CNN 中的卷积层&#xff0c;从而提高网络的…

【AI】DeepSeek 概念/影响/使用/部署

在大年三十那天&#xff0c;不知道你是否留意到&#xff0c;“deepseek”这个词出现在了各大热搜榜单上。这引起了我的关注&#xff0c;出于学习的兴趣&#xff0c;我深入研究了一番&#xff0c;才有了这篇文章的诞生。 概念 那么&#xff0c;什么是DeepSeek&#xff1f;首先百…

el-table组件样式如何二次修改?

文章目录 前言一、去除全选框按钮样式二、表头颜色的修改 前言 ElementUI中的组件el-table表格组件提供了丰富的样式&#xff0c;有一个全选框的el-table组件&#xff0c;提供了全选框和多选。 一、去除全选框按钮样式 原本默认是有全选框的。假如有一些开发者&#xff0c;因…

Three.js实现炫酷图片粒子化效果:从聚合到扩散的动态演变

一、效果展示 本特效实现了一个基于图片像素的智能粒子系统&#xff0c;通过Three.js引擎驱动&#xff0c;呈现出以下惊艳效果&#xff1a; 图片粒子化&#xff1a;将任意图片转化为动态粒子系统智能聚合扩散&#xff1a;粒子在聚合状态与随机扩散状态间自然过渡物理运动模拟…