Android Retrofit框架分析(三):自动切换回主线程;bulid的过程;create方法+ServiceMethod源码了解

目录

  1. Okhttp有什么不好?
  2. bulid的过程
  3. create方法+ServiceMethod
  4. call + enqueue的过程
  5. 为什么要学习源码呢?

一、Okhttp有什么不好?

Okhttp本身来说,是一个挺好的网络框架,但,对于开发者而言,使用起来,会过于繁琐。下面我们看看一个代码:

// 1️⃣ 手动拼接URL和参数(容易出错)
HttpUrl url = HttpUrl.parse("https://api.example.com/user")
    .newBuilder()
    .addQueryParameter("id", "123")
    .build();

// 2️⃣ 创建请求对象
Request request = new Request.Builder().url(url).build();

// 3️⃣ 发起异步请求
OkHttpClient client = new OkHttpClient();
client.newCall(request).enqueue(new Callback() {
    @Override
    public void onResponse(Call call, Response response) throws IOException {
        // 4️⃣ 手动解析JSON(容易遗漏判空)
        String json = response.body().string();
        User user = new Gson().fromJson(json, User.class);

        // 5️⃣ 手动切回主线程更新UI(忘记切换会崩溃)
        runOnUiThread(() -> {
            textView.setText(user.getName());
        });
    }

    @Override
    public void onFailure(Call call, IOException e) {
        // 6️⃣ 手动处理失败逻辑(比如Toast错误)
    }
});

​问题总结​​:

  • ​代码臃肿​​:每个请求都要写重复代码(拼参数、解析JSON、线程切换)。
  • ​维护困难​​:如果接口路径或参数变更,需要全局搜索修改。
  • ​容错成本高​​:手动处理空指针、JSON解析异常、线程安全问题。

下面我们看看Retrofit的代码:

// 1️⃣ 声明接口(像写文档一样直观)
public interface ApiService {
    @GET("user")
    Call<User> getUser(@Query("id") String id); // 自动拼接参数
}

// 2️⃣ 发起请求(3行代码搞定)
ApiService service = retrofit.create(ApiService.class);
service.getUser("123").enqueue(new Callback<User>() {
    @Override
    public void onResponse(Call<User> call, Response<User> response) {
        // ✅ 自动解析JSON → User对象
        // ✅ 自动切回主线程
        textView.setText(response.body().getName());
    }
});

优化原理​​:

  • ​声明式API​​:用注解代替手动拼参数(如@GET定义接口路径,@Query自动拼接URL参数)。
  • ​自动解析​​:通过GsonConverter直接将JSON转成User对象。
  • ​线程安全​​:回调时自动切换回主线程(背后是MainThreadExecutor)。

那么他是如何做到的呢?接下来,我们看看源码。


二、bulid的过程

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.example.com/")  // 必填:API根路径
    .client(new OkHttpClient())          // 选填:自定义OkHttp(比如加日志拦截器)
    .addConverterFactory(GsonConverterFactory.create()) // 选填:数据解析器
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 选填:适配RxJava
    .build();

这个主要是做什么?可以理解为就是将所需的参数全部保存起来,方便后面使用,比如url,数据解析器等,都是为后面发起请求,和接收响应进行使用,使用bulid构建一个Retrofit,这就是bulid的作用。我们可以进入他的源码看看:

比如addConverterFactory以及addCallAdapterFactory方法,都是使用List来保存起来,

在这里插入图片描述

url也是

在这里插入图片描述

然后使用bulid构建一个Retrofit。

在这里插入图片描述

建造过程核心逻辑​​:

  1. ​校验必填参数​​:比如baseUrl不能为空。
  2. ​设置默认组件​​:如果没配置CallAdapter,默认用ExecutorCallAdapterFactory(处理主线程回调)。
  3. ​组合所有配置​​:将ConverterCallAdapter等组件打包到Retrofit对象中。

三、create方法+ServiceMethod

// 1️⃣ 声明接口(像写文档一样直观)
public interface ApiService {
    @GET("user")
    Call<User> getUser(@Query("id") String id); // 自动拼接参数
}

// 2️⃣ 发起请求(3行代码搞定)
ApiService service = retrofit.create(ApiService.class);
service.getUser("123");

当我们调用retrofit.create方法的时候,我们看看内部做了什么。

在这里插入图片描述

通过 Proxy.newProxyInstance 创建接口的代理对象,那么当我们调用service.getUser(“123”)的时候,代理对象的所有方法调用都会路由到 InvocationHandler.invoke()。让所有的接口都走 invoke函数,这样就可以拦截调用函数的执行,从而将网络接口的参数配置归一化。这个invoke方法,就是典型的AOP思想,在中间切开一个口。

invoke函数是如何完成网络请求,从这个retrofit到okhttp呢?

接下来,我们看看loadServiceMethod方法

在这里插入图片描述

这个方法返回了一个ServiceMethod,这里面主要做了什么?解析方法上的 @GET@POST 等注解,解析 @Query@Path@Body 等参数注解,解析结果会被缓存到 serviceMethodCache 避免重复解析。

每个接口方法(如 getUser())首次调用时都会生成专属的 ServiceMethod,即使同一个接口中的不同方法(如 getUser()login()),也会生成不同的 ServiceMethod,然后通过 serviceMethodCache 的 ConcurrentHashMap 缓存起来,Key 为 Method 对象。


四、call + enqueue的过程

那么接口方法上的所有信息,参数都已经拿到了,也解析好了,接下来干嘛?我们继续看回源码这里,会调用invoke方法。

在这里插入图片描述
在这里插入图片描述

创建 OkHttpCall 对象,通过传递进来的参数,json解析成对应的bean,返回封装了okhttp的call
在这里插入图片描述

在这里插入图片描述

call有了以后,接下来就是调用enqueue方法

在这里插入图片描述

在得到response以后,要返回给主线程

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

底层还是handler。


五、为什么要学习源码呢?

一开始的时候,在想,为什么要看源码,看了源码以后,你了解他的原理,你也可以运用他的技术,用到其他方面,比如注解的使用,动态代理的使用。

然后也能了解他的底层逻辑,后面我们写retrofit代码的时候,也会有一种恍然大悟的感觉,比如回调的这个地方,已经自动会切换到主线程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前期后期

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值