字节跳动算法工程师面经,retrofit源码解析(1),大专生三面蚂蚁金服

        @Override

        public void onFailure(retrofit2.Call<HttpResponse<List<Coin>>> call, Throwable t) {



        }

    });



接口定义好以后,是通过动态代理的方式把接口转换为实际请求,ServiceMethod对应的就是一个一个的接口方法。  

create方法中:



public T create(final Class service) {

Utils.validateServiceInterface(service);

//1、会先判断是否是一个有效的method,判断是否有效会先执行loadServiceMethod方法

if (validateEagerly) {

  eagerlyValidateMethods(service);

}

//2、然后通过动态代理invoke方法中解析方法的注解(这个方法里面同样要执行loadServiceMethod方法)。

return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },

    new InvocationHandler() {

      private final Platform platform = Platform.get();



      @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)

          throws Throwable {

//invoke方法中3行最经典的代码(也是retrofit中最核心的3行代码):

//retrofit的核心是这3行代码,3行代码的核心是ServiceMethod

        ServiceMethod<Object, Object> serviceMethod =

            (ServiceMethod<Object, Object>) loadServiceMethod(method);

        OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);

        return serviceMethod.callAdapter.adapt(okHttpCall);

      }

    });

}




> **第一行核心代码解析(ServiceMethod<Object, Object> serviceMethod =  

> (ServiceMethod<Object, Object>) loadServiceMethod(method)😉**



//获得ServiceMethod,先从ServiceMethodCache中获取,如果缓存中没有,再重新构建,然后再把新获取的缓存到ServiceMethodCache中

ServiceMethod<?, ?> loadServiceMethod(Method method) {

ServiceMethod<?, ?> result = serviceMethodCache.get(method);

if (result != null) return result;



synchronized (serviceMethodCache) {

  result = serviceMethodCache.get(method);

  if (result == null) {

//如果没有缓存就重新创建一个ServiceMethod实例并缓存

    result = new ServiceMethod.Builder<>(this, method).build();

    serviceMethodCache.put(method, result);

  }

}

return result;

}




**下面具体解析:result = new ServiceMethod.Builder<>(this, method).build();**  

如何通过动态代理把我们定义的网络接口转换为ServiceMethod(实际请求对象)?



下面看看ServiceMethod类,有几个重要的变量,这几个变量包含了我们所有的网络请求的基本信息,它的初始化也是builder模式:



final class ServiceMethod<R, T> {

//OkHttp中的Call

final okhttp3.Call.Factory callFactory;

//网络请求适配器比如(RxjavaCallAdapter)

final CallAdapter<R, T> callAdapter;

private final HttpUrl baseUrl;

//数据转换器(GsonConverterAdapter)

private final Converter<ResponseBody, R> responseConverter;

//get post delete 等

private final String httpMethod;

//相对地址(和baseurl拼接在一起)

private final String relativeUrl;

//请求头

private final Headers headers;

//body

private final MediaType contentType;

private final boolean hasBody;

private final boolean isFormEncoded;

private final boolean isMultipart;

//最核心的,方法参数的处理器(方法和方法上面的注解都是它解析的)

private final ParameterHandler<?>[] parameterHandlers;

一、下面是builder模式内部类,注意3,4,5

Builder(Retrofit retrofit, Method method) {

//1、retrofit对象

  this.retrofit = retrofit;

//2、请求方法名

  this.method = method;

//3、网络请求接口里面的注解

  this.methodAnnotations = method.getAnnotations();

//4、获取请求接口中参数的类型

  this.parameterTypes = method.getGenericParameterTypes();

//5、获取注解里面的内容

  this.parameterAnnotationsArray = method.getParameterAnnotations();

}

}

二、build()方法

根据responseType和方法中的注解来解析整个需要的内容

public ServiceMethod build() {

//1、通过网络请求方法的返回值和注解类型,从retrofit对象中获取请求适配器。

  callAdapter = createCallAdapter(); 

//2、根据网络请求接口方法的返回值和注解类型,从retrofit对象中获取这个请求适配器返回的数据类型

  responseType = callAdapter.responseType();

  if (responseType == Response.class || responseType == okhttp3.Response.class) {

    throw methodError("'"

        + Utils.getRawType(responseType).getName()

        + "' is not a valid response body type. Did you mean ResponseBody?");

  }

//3、创建数据转换器

  responseConverter = createResponseConverter();

//4、遍历注解,解析注解

  for (Annotation annotation : methodAnnotations) {

    parseMethodAnnotation(annotation);

  }

//5、遍历参数,解析参数

  for (int p = 0; p < parameterCount; p++) {

    parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);

  }

总结build()方法:

根据返回值类型和方法中的注解来从网络请求适配器工厂和数据转换器工厂分别获取到(request)请求适配器(callAdapter)和(response) 数据返回转换器(converter);

然后会根据参数注解来获取到参数;最后调用parseParameter解析结果中的参数。




> 其中里面的方法:



private CallAdapter<T, R> createCallAdapter() {

//网络接口方法返回的类型

  Type returnType = method.getGenericReturnType();

  if (Utils.hasUnresolvableType(returnType)) {

    throw methodError(

        "Method return type must not include a type variable or wildcard: %s", returnType);

  }

  if (returnType == void.class) {

    throw methodError("Service methods cannot return void.");

  }

//获取网络请求接口里面的注解

  Annotation[] annotations = method.getAnnotations();

  try {

    //returnType:网络请求方法的返回值 ;annotations:注解类型

    return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);

  } catch (RuntimeException e) { // Wide exception range because factories are user code.

    throw methodError(e, "Unable to create call adapter for %s", returnType);

  }

}

调用:

public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {

return nextCallAdapter(null, returnType, annotations);

}

调用:

public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,

  Annotation[] annotations) {

checkNotNull(returnType, "returnType == null");

checkNotNull(annotations, "annotations == null");

//遍历callAdapter的工厂集合寻找合适的工厂,然后通过get方法来获取CallAdapter,最后赋值给ServiceMethod的callAdapter

int start = adapterFactories.indexOf(skipPast) + 1;

for (int i = start, count = adapterFactories.size(); i < count; i++) {

  CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);

  if (adapter != null) {

    return adapter;

  }

}


private Converter<ResponseBody, T> createResponseConverter() {

//获取接口中注解

  Annotation[] annotations = method.getAnnotations();

  try {

    return retrofit.responseBodyConverter(responseType, annotations);

  } catch (RuntimeException e) { // Wide exception range because factories are user code.

    throw methodError(e, "Unable to create converter for %s", responseType);

  }

}

调用:

public Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {

return nextResponseBodyConverter(null, type, annotations);

}

调用:

public Converter<ResponseBody, T> nextResponseBodyConverter(

  @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {

checkNotNull(type, "type == null");

checkNotNull(annotations, "annotations == null");

//遍历converter的工厂集合寻找合适的工厂,然后通过get方法来获取converter,最后赋值给ServiceMethod的converter

int start = converterFactories.indexOf(skipPast) + 1;

for (int i = start, count = converterFactories.size(); i < count; i++) {

  Converter<ResponseBody, ?> converter =

      converterFactories.get(i).responseBodyConverter(type, annotations, this);

  if (converter != null) {

    //noinspection unchecked

    return (Converter<ResponseBody, T>) converter;

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

写在最后

对程序员来说,很多技术的学习都是“防御性”的。也就是说,我们是在为未来学习。我们学习新技术的目的,或是为了在新项目中应用,或仅仅是为了将来的面试。但不管怎样,一定不能“止步不前”,不能荒废掉。

![
[]


文章以下内容会给出阿里与美团的面试题(答案+解析)、面试题库、Java核心知识点梳理等

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

2583219038)]

文章以下内容会给出阿里与美团的面试题(答案+解析)、面试题库、Java核心知识点梳理等

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值