2024年HarmonyOS鸿蒙最新梳理Retrofit的知识体系(2),头条HarmonyOS鸿蒙面试节奏

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!


img
img

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

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

需要这份系统化的资料的朋友,可以戳这里获取

  • 代理类与委托类有着同样的接口
  • 代理类主要为委托类预处理消息,过滤消息,然后把消息发送给委托类,以及事后处理消息等等
  • 一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,为提供特定的服务

以上是普通代理模式(静态代理)它是有一个具体的代理类来实现的

动态代理+反射

那么Retrofit用到的动态代理呢?答案不言而喻,所谓动态就是没有一个具体的代理类,我们看到Retrofitcreate函数中,它是可以为委托类对象生成代理类, 代理类可以将所有的方法调用分派到委托对象上反射执行,大致如下

  • 接口的classLoader
  • 只包含接口的class数组
  • 自定义的InvocationHandler()对象, 该对象实现了invoke() 函数, 通常在该函数中实现对委托类函数的访问

这就是在create函数中所使用的动态代理及反射

扩展:通过这些文章,了解更多动态代理与反射

反射,动态代理在Retrofit中的运用
Retrofit的代理模式解析

Retrofit注解是怎么进行解析的?

在使用Retrofit的时候,或者定义接口的时候,在接口方法中加入相应的注解(@GET,@POST,@Query@FormUrlEncoded等),然后我们就可以调用这些方法进行网络请求了;那么就有了问题,为什么注解可以完整的覆盖网络请求?我们知道,注解大致分为三类,通过请求方法、请求体编码格式、请求参数,大致有22种注解,它们基本完整的覆盖了HTTP请求方案 ;通过它们我们确定了网络请求request的具体方案;

此时,就抛出了开始的问题,Retrofit注解是怎么被解析的呢?这里就要熟悉Retrofit中的ServiceMethod类了,总的来说,它首先选择Retrofit里提供的工具(数据转换器converter,请求适配器adapter),相当于就是具体请求Request的一个封装,封装完成之后将注解进行解析;

下面通过官方提供例子来说明下ServiceMethod组成的部分

其中 @GET("users/{user}/repos"是由parseMethodAnnotation负责解析的;@Path参数注解就由对应ParameterHandler进行处理,剩下的Call<List<Repo>毫无疑问就是使用CallAdapter将这个Call 类型适配为用户定义的 service method 的返回类型。

那么ServiceMethod是怎么对注解进行解析的呢,来简单梳理下它的源码

  • 首先,在loadService方法中进行检测,禁止静态方法,这里Retrofit笔者使用的是2.9.0版本,不再是直接调用ServiceMethod.Builder(),而是使用缓存的方式调用ServiceMethod.parseAnnotations(this, method),将它转为RequestFactory对象,其实本地大同小异,原理是差不多的

final class RequestFactory {
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
return new Builder(retrofit, method).build();
}

  • 同样在RequestFactory中也是使用Builder模式,其实就是封装了一层,传入retrofit-method两个参数,在这里面我们调用了Method类获取了它的注解数组methodAnnotations,型参的类型数组parameterTypes,型参的注解数组parameterAnnotationsArray

Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
this.methodAnnotations = method.getAnnotations();
this.parameterTypes = method.getGenericParameterTypes();
this.parameterAnnotationsArray = method.getParameterAnnotations();
}

  • 然后在build方法中,它会创建一个ReqeustFactory对象,最终解析它通过HttpServiceMethod又转换成ServiceMethod实例,这个方法里主要就是针对注解的解析过程,由于源码非常长,感兴趣的同学可以去详细阅读下,这里大概概括下几个重要的解析方法
  1. parseMethodAnnotation

该方法就是确定网络的传输方式,判断加了哪些注解,下面借用一张网络上的图表达会更直观点

  1. parseHttpMethodAndPath,parseHeaders

我们通过上图也可以看到,其实就是解析httpMethodheaders,它们都是在parseMethodAnnotation方法中被调用的,从而进行细化。前者确定的是请求方法(get,post,delete等),后者顾名思义确定的是headers头部;前者会检测httpMethod,它不允许有多个方法注解,会使用正则表达式进行判断,url中的参数必须用括号占位,最终提取出了真实的urlurl中携带的参数名称;后者就是解析当前Http请求的头部信息

  • 经过以上方法注解处理以及验证,在build方法中还要对参数注解进行处理

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

它循环进行参数的验证处理,通过parseParameter方法最后一个参数判断是否继续,参考下网络上的图示

简单说下ParameterHandler是怎么处理这个参数注解的?它会通过进行两项校验,分别是对不确定的类型合法校验路径名称的校验,然后就是一堆参数注解的处理,分析源码后可以看到ParameterHandler最终都组装成了一个RequestBuilder,那么它是用来干神马的?答案是生成OKHttpRequest,网络请求还是交给OKHttp来完成

以上简单分析了下Retrofit注解的解析过程,需要深入了解的同学请自行探索。

如果同学对注解不太熟悉,想要了解Java注解的相关知识点可以阅读这篇文章—>(Retrofit注解)

Retrofit如何将注解封装成OKHttpcall

上个问题已经知道了Retrofit中的ServiceMethod对会注解进行解析封装,这时候各种网络请求适配器,请求头,参数,转换器等等都准备好了,最终它会将ServiceMethod转为Retrofit提供的OkHttpCall,这个就是对okhttp3.Call的封装,答案已经呼之欲出了。

@Override
final @Nullable ReturnT invoke(Object[] args) {
Call call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}

换种说法,相当于在ServiceMethod中已经将注解转变为url +请求头+参数等等格式,对照OKHttp请求流程,是不是已经完成了构建Request请求了,它最终要变成Okhttp3.call才能进行网络请求,所以OkHttpCall基本上就是做了这么一件事情,下面有张图可以直观看下ServiceMethod大概做了哪些事情

接着我们看下okhttpCall中的enqueue方法,它会去创建一个真实的Call,这个其实就是OKHttp中的call,接下来的网络请求工作就交给OKHttp来完成

private okhttp3.Call createRawCall() throws IOException {
okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
if (call == null) {
throw new NullPointerException(“Call.Factory returned null.”);
}
return call;
}

到这里,说白了Retrofit其实没有任何与网络请求相关的东西,它最终还是通过统一解析注解Request去构建OkhttpCall执行,通过设计模式去封装执行OkHttp

Rretrofit是怎么完成线程切换和数据适配的

Retrofit在网络请求完成后所做的就只有两件事,自动线程切换和数据适配;那么它是如何完成这些操作的呢?

关于数据适配

其实这个在上文注解解析问题中已经回答了一部分了,这里我大概总结下流程,具体的数据解析适配过程细节需要大家私下去深入探讨;在封装的OkhttpCall调用OKHttp进行网络请求后会拿到接口响应结果response,这时候就要进行数据格式的解析适配了,会调用parsePerson方法,里面最终还是会调用RetrofitconverterFactories拿到数据转换器工厂的集合其中的一个,所以当我们创建Retrfoit中进行addConvetFactory的时候,它保存在了Retrofit当中,交给了responseConverter.convert(responsebody),从而完成了数据转换适配的过程

关于线程切换

首先我们要知道线程切换是发生在什么时候?毫无疑问,肯定是在最后一步,当网络请求回来后,且进行数据解析后,那这样我们向上寻根,发现最终数据解析由HttpServiceMethod之后它会调用callAdapter.adapt()进行适配

protected Object adapt(Call call, Object[] args) {
call = callAdapter.adapt(call);

}

这意味着callAdapter会去包装OkhttpCall,那么这个callAdapter是来自哪里的,追本朔源,它其实在Retrofit中的build会去添加defaultCallAdapterFactories,这个方法里就调用了DefaultCallAdapterFactory,真正的线程切换就在这里

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

这个默认的defaultCallAdapterFactories会传入平台的defaultCallbackExecutor(),由于我们平台是Android,所以它里面存放的就是主线程的Executor,它里面就是一个Handler

static final class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());

@Override
public void execute(Runnable r) {
handler.post®;
}
}

到这来看下DefaultCallAdapterFactory中的enqueue(代理模式+装饰模式), 这里面使用了一个代理类delegate,它其实就是Retrofit中的OkhttpCall,最终请求结果完成后使用callbackExecutor.execute()将线程变为主线程,最终又回到了MainThreadExecutor当中

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!


img
img

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

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

需要这份系统化的资料的朋友,可以戳这里获取

yulXcS-1715241353868)]

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

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

需要这份系统化的资料的朋友,可以戳这里获取

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要设计和实现一个基于HarmonyOS的视频播放器,需要以下软件支持: 1. 开发工具:使用HarmonyOS开发工具包(HDK)来开发和调试应用程序。HDK提供了一系列开发工具,如集成开发环境(IDE)、模拟器、调试工具等。 2. 视频解码器:要支持多种视频格式,需要使用能够解码多种视频格式的解码器。一些流行的视频解码器包括FFmpeg、GStreamer等。 3. 音频解码器:除了视频解码器外,还需要支持多种音频格式。一些流行的音频解码器包括FFmpeg、GStreamer等。 4. 播放器框架:要实现一个完整的视频播放器,需要一个播放器框架。一些流行的播放器框架包括VLC、MPV、ExoPlayer等。 5. 界面设计工具:设计和实现用户界面需要使用界面设计工具。一些流行的界面设计工具包括Sketch、Adobe XD、Figma等。 6. 数据库:要实现一些基本功能,如播放列表、播放历史等,需要一个数据库来存储数据。一些流行的数据库包括SQLite、MySQL、MongoDB等。 7. 网络库:要支持在线播放,需要使用网络库来获取网络数据。一些流行的网络库包括OkHttp、Retrofit等。 8. 测试工具:为确保应用程序的质量,需要使用测试工具进行测试。一些流行的测试工具包括JUnit、Robotium、Appium等。 以上是基于HarmonyOS的视频播放器所需要的软件支持,当然具体的软件支持还需要根据实际情况而定。 ### 回答2: 设计和实现基于HarmonyOS的视频播放器需要以下支持软件: 1. HarmonyOS SDK:该软件提供了视频播放所需的开发工具和接口,包括音视频解码、音频处理、画面渲染等功能的API,以便开发人员可以根据实际需求进行自定义开发。 2. 多媒体框架:视频播放器需要一个强大的媒体框架来管理视频文件的导入、解码和播放等操作。多媒体框架能够支持多种视频格式的解码,在播放过程中实现流畅的画面渲染和音频输出。 3. 网络支持:视频播放器需要能够通过网络获取视频资源,因此需要支持网络协议,如HTTP、RTSP等,以便从远程服务器或者云存储中下载或者在线播放视频。 4. 用户界面:对于视频播放器来说,用户界面是非常重要的,需要一个直观、易用的界面设计来提供播放、暂停、快进、调节音量等常用操作,以及支持播放列表、播放历史等功能。 5. 媒体管理:视频播放器需要能够管理用户本地视频库中的视频文件,包括扫描本地文件、获取视频信息和元数据、生成缩略图、提供搜索和排序功能等。 6. 多媒体控制:视频播放器需要支持多种媒体控制方式,如通过按键、手势、远程控制等方式来控制播放器的操作,以提供更加便捷的用户体验。 7. 视频扩展功能:为了提供更广泛的功能,视频播放器还可以支持一些扩展功能,如字幕显示、屏幕投射、画中画、VR播放等,以满足用户的多样化需求。 综上所述,设计和实现基于HarmonyOS的视频播放器需要以上提到的关键支持软件,以便提供功能丰富、稳定流畅的视频播放体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值