本文將在RxHttp的基礎上帶你們如何優雅的設置BaseUrl,若是您還未了解RxHttp,請移步php
RxHttp 一條鏈發送請求,新一代Http請求神器(一)java
RxHttp 一條鏈發送請求之強大的數據解析功能(二)git
RxHttp 一條鏈發送請求之強大的Param類(三)github
RxHttp 一條鏈發送請求之註解處理器 Generated API(四)app
RxHttp一經推出,就有人問:難道Retrofit很差用嗎?爲啥還要本身去封裝呢?藉此文,跟你們簡單聊一聊。 爲何要重複造輪子?無非就一個緣由post
Retrofit哪裏很差用,用起來不夠優雅?ui
首先
,我以爲是對文件的操做不是那麼的友好,如文件上傳/下載、上傳/下載進度監聽、斷點下載,這些都須要咱們進行二次封裝,看過Android 史上最優雅的實現文件上傳、下載及進度的監聽的同窗知道,使用RxHttp是多麼的簡單;this
而後
,是對多個baseUrl,或者說動態baseUrl
不夠友好,Retrofit要求baseUrl 必須是一個final常量,咱們想要動態修改,就只能經過增長攔截器去實現,這也是本文重點要說的;url
最後
,也是很是重要的一點,那就是Activity/Fragment銷燬時,對請求的關閉,一般咱們的作法是爲請求設置Tag,而後根據此Tag去關閉一系列請求,又或者拿到Call對象,去關閉單個請求,極其的麻煩,若是你使用RxHttp,在Activity/Fragment中,一行代碼就能搞定,而且支持在任意生命週期方法關閉請求,極其簡單高效。(注意:Retrofit結合RxJava,依然可以在RxJava中斷上下游時,調用Call對象的cancel方法,感謝評論區卓_修武
大佬的指正)spa
以上就是我重複造輪子的主要緣由,歡迎你們交(Da)流(Lian)討論,下面將進入正題。
若是你的項目中只有一個BaseUrl,那麼只須要使用@DefaultDomain
註解便可,以下:
public class Url {
@DefaultDomain() //設置爲默認域名,對final關鍵字沒有要求
public static String baseUrl = "http://ip.taobao.com/";
}
複製代碼
發送請求,咱們就能夠這樣
String url = "/service/getIpInfo.php";
RxHttp.get(url) //Get請求
.add("ip", "63.223.108.42") //添加參數
.addHeader("accept", "*/*") //添加請求頭
.addHeader("connection", "Keep-Alive")
.addHeader("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)")
.asString() //這裏返回Observable<String> 對象
//感知生命週期,並在主線程回調,Activity/fragment銷燬,自動關閉爲完成的請求
.as(RxLife.asOnMain(this))
.subscribe(s -> {
//成功回調
}, throwable -> {
//失敗回調
});
複製代碼
此時,發送請求前,RxHttp會對咱們傳入url作判斷,若是url裏已經有baseUrl,便是一條完成url連接,就不會添加@DefaultDomain
註解代表的baseUrl,不然就會添加,咱們經過日誌來觀察如下結果(過濾RxHttp)
注:
註解@DefaultDomain
只能使用一處,多處使用將編譯不經過
在上面代碼中,咱們只須要傳入一條完整的url連接,其實就已經實現了多個baseUrl的問題,而後,大部分開發者都喜歡將baseUrl 單獨寫在一個變量裏,若是每次發請求,咱們都須要以baseUrl+url
的方式去實現,顯然不夠友好,那麼RxHttp又是若是去解決的呢?很簡單,使用@Domain
註解,以下:
public class Url {
@Domain(name = "Update")
public static String update = "http://update.9158.com";
@DefaultDomain() //設置爲默認域名,對final關鍵字沒有要求
public static String baseUrl = "http://ip.taobao.com/";
}
複製代碼
此時rebuild一下項目,RxHttp類就會自動生成一個setDomainToUpdateIfAbsent()
方法,此方法的命名規則爲setDomainTo
+@Domain註解中指定的name字段的值
+IfAbsent
,見名思議,此方法是會在域名缺席的狀況下,添加咱們指定的域名,若是沒有指定,就會添加@DefaultDomain
註解標記的默認域名。
此時發請求,咱們就能夠這樣:
String destPath = getExternalCacheDir() + "/" + System.currentTimeMillis() + ".apk";
RxHttp.get("/miaolive/Miaolive.apk")
.setDomainToUpdateIfAbsent() //使用指定的域名
.asDownload(destPath) //注意這裏使用DownloadParser解析器,並傳入本地路徑
.as(RxLife.asOnMain(this)) //感知生命週期,並在主線程回調
.subscribe(s -> {
Log.d("RxHttp", "download success \npath=" + s);
//下載成功,回調文件下載路徑
}, throwable -> {
//下載失敗
});
複製代碼
咱們再經過日誌來觀察一下
能夠看到,baseUrl跟url成功拼接在了一塊兒,並完成了下載操做。
@Domain
註解可使用多處,以下:
public class Url {
@Domain(name = "Baidu")
public static String update = "http://www.baidu.com";
@Domain(name = "Hao123")
public static String update = "https://www.hao123.com/";
@Domain(name = "Update")
public static String update = "http://update.9158.com";
@DefaultDomain() //設置爲默認域名,對final關鍵字沒有要求
public static String baseUrl = "http://ip.taobao.com/";
}
複製代碼
此時rebuild一下項目,RxHttp類下就會再新增setDomainToBaiduIfAbsent()
、setDomainToHao123IfAbsent()
這兩個方法,故咱們發請求就能夠調用setDomainToXXXIfAbsent
方法指定baseUrl。
某些狀況下,咱們的域名可能會被封,又或者其它緣由,致使咱們須要在app啓動的時候動態配置域名,若是你使用Retrofit的話,因爲Retrofit要求baseUrl必須是final常量,因此咱們就只能經過攔截器去實現,而RxHttp對baseUrl ,沒有final關鍵字的限制,咱們只須要對baseUrl從新賦值便可,並且,能夠在代碼中屢次賦值,賦值後當即生效。
如:咱們將baseUrl裏taobao
域名改成baidu
,改完當即發送請求。
Url.baseUrl = "http://www.baidu.com"; //更改域名,將taobao域名改成baidu
RxHttp.get("/service/getIpInfo.php") //Get請求
.add("ip", "63.223.108.42") //添加參數
.addHeader("accept", "*/*") //添加請求頭
.addHeader("connection", "Keep-Alive")
.addHeader("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)")
.asString() //這裏返回Observable<Response> 對象
.as(RxLife.asOnMain(this)) //感知生命週期,並在主線程回調
.subscribe(s -> {
//成功回調
}, throwable -> {
//失敗回調
});
複製代碼
看一下日誌
能夠看到,域名成功被更改,並當即生效。因爲該接口不存在,因此返回了Html頁面代碼。怎麼樣,是否是最優雅的設置baseUrl?歡迎打臉。 其實,RxHttp遠不止本篇文章說的這些優勢,更多彩蛋,請查看源碼
本文的目的並不在於說Retrofit很差,而是提供一種新的思路與方案,供開發者去選擇。曾經有讀者問我,有沒有打算將RxHttp融入Retrofit,Retrofit的註解請求很好用,並且寫在一個類裏,很直觀。個人回答是 NO !RxHttp若是融入Retrofit,那RxHttp就是Retrofit,那還有什麼區別呢? 若是你喜歡將請求寫在一個類裏,RxHttp也是能實現的。以下:
public class Http {
public static Observable<List<Student>> getStudents(int id, int page, int size) {
return RxHttp.get("xxx/getStudent")
.add("id", id).add("page", page).add("size", size)
.asList(Student.class);
//後期會增長add(key,value,key,value....)可變參數方法
}
//其它請求同理
}
複製代碼
藉此機會,若是你對RxHttp感興趣,又有本身的想法,歡迎你加入維護的隊伍中。
好了,轉載請註明出處,🙏🙏🙏。
最後,歡迎你們,加羣溝通交流 RxHttp&RxLife 交流羣: 378530627
,以前忘記建羣了😅😅,但願你們能多給點建議,我會第一時間回覆。🙏🙏🙏
若是你以爲RxHttp好用,請記得給我star。萬分感謝🙏🙏🙏