声明的时候比Retrofit更加简单,而且因为是从Retrofit上改的,所以Retrofit能用的东西这个库也能用
远程依赖接入方式在最下面
ps:目前更推荐使用性能更好且跨平台的: ltttttttttttt/LazyPeopleHttp
1.如果参数不加任何注解,则默认是@Field,并且value为参数名(使用了kt反射,所以使用该特性必须用kt文件)
Retrofit原来的声明和现在的声明对比:
ps:发现目前kt反射还是效率很低,所以建议将获取Call的方法放到子线程中,或者在初始化的时候预加载
比如:
//先创建出retrofit对象,然后create出动态代理,create后再在子线程处理预加载
val retrofit=xxx
val post = retrofit.create(IPostRequest::class.java)
submitToCacheThreadPool {
//在子线程,可能需要几秒,所以在启动十秒内可能会用到的方法就手动声明@field吧!
//预初始化所有的方法,使用时更快,注意需要在子线程调用,否则会造成anr,且由于将所有方法载入,所以会增加内存消耗,属于饿汉式(空间换时间)
retrofit.preInit(IPostRequest::class.java)
}
2.POST注解自带FormUrlEncoded注解,可以在第二个参数isUseFormUrlEncoded设置为false(且如果没有参数就自动变为false),默认为自动判断
ps:再也不用在写的时候看有没有参数加@FormUrlEncoded注解了,或者删除参数的时候忘了删该注解引起的崩溃!!!
Retrofit原来的声明和现在的声明对比:
3.如果方法没有加注解,就默认加上POST和FormUrlEncoded注解(参数为空不加此注解),并且method名字=url($代替/)(如果是kt就这样写: `user$login` )
Retrofit原来的声明和现在的声明对比:
ps:因为kt的方法名不支持$符号,所以需要两边需要加 ` ,而java是支持的(但java无法享受kt反射的便捷)
pps:该方式是相当于增加了一个可选项,不是必选!!!(免杠声明)
ppps:根据kt特性,可以使用下面的方式来在接口中声明一个无参的get方法(不过可能有些鸡肋)
val info: Call //它的url就是getInfo
val `test$123`: Call //它的url就是getTest/123 方法名是getTest$123
pppps:增加修改分隔符的功能,可以将$切换成任意字符串来代替/ 将$修改成_只需要这一行代码即可: Retrofit.Builder().xxx.setMethodDelimiter("_")
4.程序运行中途可以修改Retrofit的baseUrl
这个没什么好说的
5.可以修改没有注解时的默认注解
val retrofit: Retrofit = Retrofit.Builder()
.baseUrl(HttpConfig.ROOT_URL.toString())
.defaultAnnotation(GET::class.java)//这一行
可以将默认的POST注解切换为GET注解,参数的注解也从Field注解切换为Query注解
ps:该方法仅支持GET和POST
6.将方法内所有参数合并为一个参数
比如:本来参数是{"a":1,"b":2},可以合并成{"str":"{"a":1,"b":2}"} 因为有的后端会将所有参数合并成一个并将其加密,所以考虑到有这个需求就增加了一个功能,开启只需要在初始化Retrofit的时候加入以下一行
val retrofit: Retrofit = Retrofit.Builder()
.xxx
.setSingleParameter("str")//这一行就开启了合并参数,传null表示关闭(默认)
.build()
开启后其他都不需要修改即可合并参数
如果想单独开启某个方法或关闭某个方法就可以使用方法注解:
@MergeParameter("str")//在没有全局配置的情况下开启,或在全局配置和该方法配置的key不相同时可以单独修改
@NotMergeParameter //如果开启了全局配置,则关闭该方法的合并参数
ps:该方法仅支持GET的Query和POST的Field
7.支持自定义Retrofit.Call对象来拦截默认的OkHttp的Call请求网络或做其他事情
Retrofit.Builder()
.baseUrl(Urls.HTTP_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.callFactory(PostRequest.client)
//下面这一行
.setServiceMethodFactory(SocketServiceMethodFactory(SocketManage.manager, socketAdapter, false))
.build()
.create(IPostRequest::class.java)
ps:比如用于Socket请求,源码可以参考:GitHub - ltttttttttttt/Retrofit_SocketCallAdapter: Retrofit可以直接使用OkSocket来进行网络请求,Retrofit内的东西都不需要修改,只需要将OkHttpClient换成此即可 ,使用可以参考:使用Retrofit的方式请求Socket,且Socket可以和Http无缝切换_滔lt的博客-CSDN博客_retrofit websocket
8.可以拦截短url并生成hook后的url(包括@POST之类和用@URL)
Retrofit.Builder()
.baseUrl("xxx")
xxx
.setHandlerUrlListener { oldUrl, method ->//这行
//将原有的oldUrl(短url)转换成你hook的url
//比如将所有短url前面加上 version/ 可以这样
return@setHandlerUrlListener "version/" + oldUrl
}
9.更简单的声明返回值
一般我们在接口里声明返回值都会在原有基础上包一层,比如Call
而使用下面的方式可以简化书写,其实用的是kt的特性,但估计有的同学不知道
首先在接口文件的最外层下上下面的type声明(最外层表示跟这个接口同级别)
然后就可以在接口里直接简写了,名字可以你自己起,可以看到打开这个方法的详情,它会提示你他的返回类型和具体返回类型
10.可以使用默认参数,声明的时候就可以将常量(或确认的值)直接声明好,调用的时候就不用传了
这个其实也是kt的特性,没什么好说的
11.可以直接传递list的json
使用过retrofit,然后把list当参数传递给后台的都知道,默认retrofit是不支持此功能的(或者说实现的比较怪异),一般可以通过将list转为json字符串来发送(虽然其type变成了String)
使用此框架可以简单的传递list json,只需要给list参数加上一个@ParameterIsList注解即可:
ps:如果要自定义解析参数的话可以参考这篇: 使用Retrofit时,对参数进行加密_李小白lt的博客-CSDN博客_retrofit 加密
在根项目的build.gradle文件中加入:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
app的build.gradle中加上
dependencies{
...
implementation 'com.github.ltttttttttttt:retrofit:1.3.9'
implementation 'org.jetbrains.kotlin:kotlin-reflect:1.4.10'
//todo 如果需要用到gson的拦截器之类的,但是其中包含的有原版的retrofit的引用,会导致冲突,所以可以使用下面的方法来去掉本引用的某个远程依赖
implementation 'com.squareup.retrofit2:converter-gson:2.7.0' exclude module: 'retrofit'
}
需要开启java8
android{
...
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
然后按照Retrofit的正常方式使用就可以了
混淆代码
#注:com.lt开头的需要换成你自己的包名
-keepclassmembers public interface com.lt.http.HttpFunctions {*;}#网络请求封装不能被混淆
-keep class kotlin.reflect.jvm.internal.impl.load.java.**{*; }#防止kt反射被混淆
-keep class kotlin.Metadata{*; }#防止kt元注解被混淆
-keep class com.lt.model.** { *;}#实体类不能被混淆,直接设置了一个文件夹
# Retrofit-retrofit2
-dontnote retrofit2.Platform$IOS$MainThreadExecutor
-dontwarn retrofit2.Platform$Java8
-keepattributes Signature
-keepattributes Exceptions
-keep class retrofit2.Default*{*; }
#相应序列化的,我用的kt序列化
-keepattributes *Annotation*, InnerClasses
-dontnote kotlinx.serialization.SerializationKt
-keep,includedescriptorclasses class com.lt.model.**$$serializer { *; } # <-- change package name to your app's
-keepclassmembers class com.lt.model.** { # <-- change package name to your app's
*** Companion;
}
-keepclasseswithmembers class com.lt.model.** { # <-- change package name to your app's
kotlinx.serialization.KSerializer serializer(...);
}
#OkHttp
-dontwarn okhttp3.**
-keep class okhttp3.**{*;}
-keep interface okhttp3.**{*;}
-keepattributes Signature
-keepattributes *Annotation*
-dontwarn com.squareup.okhttp.**
-keep class com.squareup.okhttp.**{*;}
-keep interface com.squareup.okhttp.**{*;}
#OkIo
-dontwarn java.nio.file.*
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
-dontwarn okio.**
-keep class okio.**{*;}
-keep interface okio.**{*;}
如果想自定义封装网络请求,又想使用动态代理方式,可以参考这一篇模仿Retrofit封装一个使用更简单的网络请求框架_滔lt的博客-CSDN博客
项目是fork的Retrofit,本项目是开源的,github地址:GitHub - ltttttttttttt/retrofit: A type-safe HTTP client for Android and the JVM
如果有问题或者建议请评论留言
(经测试,300多个方法的接口(从线上项目copy出来测试的,三千多行),用这种方式,除了前两次,后面获取Call的性能竟然比原来的还快一点,嘿嘿)
end