Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)
对项目的基本介绍
- 1.整个框架主要是给MVVM框架使用的,自己写完interface接口后,通过自定义的注解就能自动生成接口方法
- 2.用Kotlin的Flow去代替Rxjava,因为我发现RxJava功能很强大,但是大家都只是在Http层面使用了一下,既然要用Kotlin里面就已经有Flow,那我还不如少添加一个库
- 3.通过jetpack的Room数据库实现网络请求的存储,缓存策略也用过注解去完成。
- 4.发起的网络请求是与宿主生命周期绑定的,在网络请求回来之前,宿主已经销毁的话,网络请求也会中断的
其中
@AutoApi
,@AutoFlowApi
,@NetStrategy
是自定义的注解,后面会介绍到。![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/6180863a3a1246cf8ad93666de3b59fb.jpg)
文章图片
2.要先编译,会在你的接口类的文件夹下生成一个xxxRepository.class 这是通过注解自动生成的文件,使用了kotlinpoet 并且这里apiService就是通过Retrofit拿到的接口代理
![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/9fea413e4674410e909bcadb8b46a6d2.jpg)
文章图片
3.在viewmodel拿到对应Repository类的方法
![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/39fdcdd8977b4efc8baf7a707fbd959a.jpg)
文章图片
4.在对应地方通过viewmodel调用 调用接口,传入对应参数
![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/0d33f6e12a9648a88abf4360b48f7c6c.jpg)
文章图片
在合适的地方观察
![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/8ce02bd45e5b455dbe63f1f78a941672.jpg)
文章图片
Retrofit的封装 上面说到在Repository类的apiService就是通过Retrofit拿到的接口代理类。 所以先进去看看apiService好了
可以看到apiService是BaseRepository的变量 而我们生成的Repository都是继承BaseRepository的
![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/56041beac73c4e6eb43c0b84dc06aa24.jpg)
文章图片
当我们调ConfigRepository类中的方法时候,就会将
ConfigRepository
传入findNeedType
![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/5a2736c823184226b3b7e77d89ccf164.jpg)
文章图片
而
findNeedType
方法就会将ConfigRepository
对应的ConfigService
得到并且返回出去![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/5dd4e3e6084c4aba9fac2c8c9835e702.jpg)
文章图片
所以apiService就相当于这样,好像有点Retrofit的create方法的样子了
var apiService: T = HttpProvider.defaultCreate(ConfigService) as Class)
我们继续进入
HttpProvider.defaultCreate
可以看到
newRetrofit()
,并且传入了一个HttpConfig,看到这个名字就知道这是Http的配置 接着是newCreate(),接收了我们的接口service类![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/f4e9efdf98cb4f1b90baf3ef2910846c.jpg)
文章图片
首先看看newRetrofit方法 这几行代码就是创建了一个Retrofit对象并且保存起来,最后返回出去。 但是他是怎么和HttpConfig联系起来的呢?
![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/e0a47e92c8cc4f839b2469f72346deb0.jpg)
文章图片
我们可以看到这里将生成的Retrofit.Builder()传给了
HttpConfig的方法build里
,我们进去看一看![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/93f533dd21b8467fad5449f0d6c99ebc.jpg)
文章图片
可以看到这里就是我们再熟悉不过的Retrofit的配置环节
![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/f45843644959409eaa3eceac921a33fd.jpg)
文章图片
所以通过newRetrofit方法,我们就将Retrofit对象配置好并且拿到Retrofit对象,还保存起来方便下次复用
在看看newCreate()方法 这是个扩展函数,是Retrofit的扩展函数 将传入的ConfigService通过Retrofit.create()生成代理类,并且保存起来复用
![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/95194c6c623c423794dd5094b41dccd8.jpg)
文章图片
注解的介绍 1.AutoApi 我们从最简单的
AutoApi
做引子,开始介绍整个注解框架只要你的接口类方法中使用了这个注解,就会生成
suspend
方法,非常的简单 接着我们来看看他是怎么实现的![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/be35229c7cb440eaafab8a3ea7f61c9d.jpg)
文章图片
![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/aa82f71928624019b3963aed05ef877d.jpg)
文章图片
看一下这个注解是怎么定义的
注解是支持有默认值的,因为kotlin的方法是可以在变量中直接赋初值的,这样调用就不用传值了,所以这里也做一个支持,让调用时候更加简洁
![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/c53f9d29e0854e64823e47b43068085e.jpg)
文章图片
生成的流程
![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/af9f3c840e4246d5a6b59a45826d79a0.jpg)
文章图片
代码的分析
这里还是用ConfigService来分析
![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/2f786e04ba924a1d99338fbb6ac06a45.jpg)
文章图片
- 1.首先流程图,我们会遍历出使用这个注解的类,此时我们就已经拿到了ConfigService这个元素的所有信息了。
- 2.接着我们会对ConfigService将包装起来,将他存在RepositoryClass类中。
![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/f727e7c5e3974d5882fd9a0d9d9a0a03.jpg)
文章图片
- 3.会将ConfigService里的方法包装成AutoMethod(不同的注解会有不同的类型),存入RepositoryClass的method变量中
![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/2a938150d9c44f39b17ec707225200a1.jpg)
文章图片
![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/b1947299f20648ea871f7b500011ebaf.jpg)
文章图片
通过上述操作后,repositoryMap就存在所有使用过AutoAPi注解的类了,再将他做遍历,传入Repository类的生成器RepositoryClassBuilder
![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/383df36a688446cdb8eedcb042cb5229.jpg)
文章图片
这个如果不添加
startFuncBuild
方法的话,这段代码就只会生成open class ConfigRepository : BaseRepository() {}
![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/4d5391161b4049cea5c395cf8693498f.jpg)
文章图片
再来看看
startFunBuild
,根据你当前类中的方法使用的注解去选择对应的方法处理器![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/da54af11e6bc41378c0a969eb5c12494.jpg)
文章图片
所有的方法处理器都是继承
AbsFuncBuilder
的 而子类需要对方法内的具体内容做输出,也可以在方法参数上做添加![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/70c835163b984735922bf886cc93d94f.jpg)
文章图片
AbsFuncBuilder
类只会生成如下代码,他会将前面RepositoryMethod
收集的信息做一个输出。但是具体内容还是交由子类去输出的,因为每个注解对应输出的方法体是不一样的suspend fun config2(page: String = "GS"): List {
// 具体内容是由子类完成的
}
2.NetStrategy注解 这个注解可以传4个参数
strategy
是缓存策略,effectiveTime
是缓存时间,timeUnit
是时间单位。缓存策略默认是添加在方法上的,有时候同一个接口可能会因为不同场景而使用不同的缓存策略。
- 比如在刚进入主页时,使用页面初始化CacheFirst
- 页面初始化后,再次下拉加载数据,使用NetCache
- 在当前主页上拉加载,使用NetOnly
所以用
isNeedAddParameter
来判断,需不需要在方法参数中添加缓存策略的参数![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/a7ec6d4ee7064197bf92e42acfe49758.jpg)
文章图片
代码的分析
NetStrategy的收集必须放在注解处理器的最后面,因为我展示想不到有什么好办法可以知道,NetStrategy这个注解,是与哪个方法注解捆绑使用了。
所以必须在前面的注解收集完毕后,当我再次收集使用过NetStrategy注解的方法时,拿到方法名,再与repositoryMap中储存的类的方法名做比较,如果一致,则表示该方法使用了NetStrategy注解,需要做缓存
![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/0bca31c69a214c48947c0f913075bbeb.jpg)
文章图片
3.AutoFlowApi注解介绍 使用注解生成的代码
下面分析一下生成方法的各个方法
![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/2e9c7c3fd5db4cd1b7132b599df5d3ad.jpg)
文章图片
viewModelScopeCoroutine
一个与viewmodel生命周期绑定的协程,默认在主线程运行
![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/50492b85d7e84638903111b0d6149642.jpg)
文章图片
![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/158c9383fd8445b887d573ef2f5ae89e.jpg)
文章图片
这里不好解释,我直接画图了
![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/2896898230ca4a14b5f7724378cdce23.jpg)
文章图片
CoroutineDataFetcher { apiService.getData() }.startFetchData()
apiService.getData() 就是发起网络请求,看一下CoroutineDataFetcher
![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/b28046220dc04d66ba010431ac46ec95.jpg)
文章图片
startFetchData(),就是根据传入的缓存参数,去找到对应的缓存策略发起Http请求的方法,很简单看一看就好
![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/5ee62464218a4b5bbd3d1aa4e3235c32.jpg)
文章图片
代码的分析
通过上面分析我们可以知道,你新写一个注解,其实就只需要编写两个类就好了
- 一个继承
RepositoryMethod
的参数收集器 - 一个继承
AbsFuncBuilder
的方法具体内容输出器
AutoFlowMethod
可以说和 AtoMethod 一模一样了,都是收集默认参数 不一样的地方就是下面的一些配置
![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/1a617b9af859400899a49683eb1025fd.jpg)
文章图片
通过重写
AbsFuncBuilder
的暴露出来的配置方法,去修改方法的配置信息,比如图中的isNullable
,方法返回值能否为nullisNeedSuspend
,方法是否是需要suspend关键字isNeedReturnType
,方法是否需要返回值
![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/3436a495d66447928b62be7c30f8f1f5.jpg)
文章图片
AutoFlowApiFuncBuilder
这个是AutoFlowApi注解最关键的方法了,里面代码比较多,但是也没什么好解释的,就是对kotlinpoet的使用,比较繁琐且无聊。
就是将你要生成的语句写出来,然后变量用规定字符代替
![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/9aa91e5d463944a88debb96bbac2349b.jpg)
文章图片
接着就是生成句子,将语句里面的规定字符,用你的变量去替代就好了
![Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)](https://img.it610.com/image/info9/4480e681ad694c4c91b0ff51280794ca.jpg)
文章图片
结尾 其实这个框架写的时候没考虑其全面性和兼容性,就打算先写出来试一试。其实还有很多地方可以修改和扩展。
【Android开发(使用Kotlin+协程+自定义注解+Retrofit的网络框架)】今天的文章就到这里,感谢您的阅读,有问题可以在评论区留言探讨,期待与大家共同进步。喜欢的话不要忘了三连。大家的支持和认可,是我分享的最大动力。
推荐阅读
- android第三方框架(五)ButterKnife
- 深入理解Go之generate
- 由浅入深理解AOP
- 【译】20个更有效地使用谷歌搜索的技巧
- mybatisplus如何在xml的连表查询中使用queryWrapper
- MybatisPlus|MybatisPlus LambdaQueryWrapper使用int默认值的坑及解决
- MybatisPlus使用queryWrapper如何实现复杂查询
- Android中的AES加密-下
- 标签、语法规范、内联框架、超链接、CSS的编写位置、CSS语法、开发工具、块和内联、常用选择器、后代元素选择器、伪类、伪元素。
- 带有Hilt的Android上的依赖注入