更易于使用的Retrofit(不用写注解)
前言
聲明的時候比Retrofit更加簡單,而且因為是從Retrofit上改的,所以Retrofit能用的東西這個庫也能用
修改的地方
1.如果參數不加任何注解,則默認是@Field,并且value為參數名(使用了kt反射,所以使用該特性必須用kt文件)
Retrofit原來的聲明和現在的聲明對比:
ps:發現目前kt反射還是效率很低,所以建議將獲取Call的方法放到子線程中,或者在初始化的時候預加載
比如:
//先創建出retrofit對象,然后create出動態代理,create后再在子線程處理預加載val retrofit=xxxval 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<String> //它的url就是getInfo val `test$123`: Call<String> //它的url就是getTest/123 方法名是getTest$123pppps:增加修改分隔符的功能,可以將$切換成任意字符串來代替/? 將$修改成_只需要這一行代碼即可: 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請求,源碼可以參考:https://github.com/ltttttttttttt/Retrofit_SocketCallAdapter? ,使用可以參考:https://blog.csdn.net/qq_33505109/article/details/114189564
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<BaseBean<XXX>>,這樣寫起來比較麻煩,而且容易忘了寫封裝的那一層
而使用下面的方式可以簡化書寫,其實用的是kt的特性,但估計有的同學不知道
首先在接口文件的最外層下上下面的type聲明(最外層表示跟這個接口同級別)
然后就可以在接口里直接簡寫了,名字可以你自己起,可以看到打開這個方法的詳情,它會提示你他的返回類型和具體返回類型
10.可以使用默認參數,聲明的時候就可以將常量(或確認的值)直接聲明好,調用的時候就不用傳了
這個其實也是kt的特性,沒什么好說的
使用方式
在根項目的build.gradle文件中加入:
allprojects {repositories { ...maven { url 'https://jitpack.io' }} }app的build.gradle中加上
dependencies{...implementation 'com.github.ltttttttttttt:retrofit:1.3.5'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_8targetCompatibility 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'skotlinx.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.**{*;}最后
如果想自定義封裝網絡請求,又想使用動態代理方式,可以參考這一篇https://blog.csdn.net/qq_33505109/article/details/104920101
項目是fork的Retrofit,本項目是開源的,github地址:https://github.com/ltttttttttttt/retrofit
如果有問題或者建議請評論留言
(經測試,300多個方法的接口(從線上項目copy出來測試的,三千多行),用這種方式,除了前兩次,后面獲取Call的性能竟然比原來的還快一點,嘿嘿)
end
總結
以上是生活随笔為你收集整理的更易于使用的Retrofit(不用写注解)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 接入Tinker热修复和踩坑
- 下一篇: 更新至Android Studio4.1