天天看點

如何用 Retrofit 2 在安卓上實作 HTTP 通路?

最近,筆者對安卓開發的興趣愈發濃厚,而且不斷嘗試了許多傳聞很棒的開發庫 -- 大部分也真的很不錯。于是打算寫一個系列文章,介紹使用這些讓人驚歎的庫建立安卓示例應用的實踐。這樣,讀者可以自行判斷,這些庫有多好用。本文是該系列的第一篇。

今天,筆者要研究對應用來說,使用 retrofit 2 的 http 用戶端有多複雜,以及能帶來什麼好處。retrofit是square inc.釋出在開源社群的一款令人歎為觀止的工具。它是一個類型安全的 http 用戶端,适用于安卓和 java 應用。

類型安全 http 用戶端主要意味着,你隻需關心發送出去的網絡請求的語義,而不必考慮 url 建構的細節,以及參數設定是否正确之類的事。retrofit應對這些易如反掌,你隻需寫幾個接口即可。就是這麼簡單!

我們通過一個例子來看看它是怎麼實作的。筆者已經把這裡所有的代碼都放在了 github 的 資源庫裡。如你所知,最好的學習方法就是檢視這些代碼,自己調試調試。

首先,筆者在 android studio 裡建了一個空項目。老實說,每次看到歡迎界面上出現的那堆有關相容性、以及應用所支援的 api 的選項,筆者都會感到非常迷茫。

如何用 Retrofit 2 在安卓上實作 HTTP 通路?
如何用 Retrofit 2 在安卓上實作 HTTP 通路?

好在我們隻是弄個“玩具”項目而已,是以我們可以大膽地選擇最新的 sdk,然後快速掠過項目向導,進入我們偉大的「hello world」安卓應用。

如果你自己不想糾結這些選項,可以直接點選這個 github 的連結,導入筆者送出的現成項目:floating button app skeleton.

通常,筆者在所有項目中都會啟用 jrebel for android。這是一個 android studio 的插件。“啟用它”基本上意味着,隻需點選一下自定義按鈕就能運作應用,其餘所有工作都交給它了。jrebel for android 對安卓開發者來說是一款提升效率的工具,它可以在運作着的裝置和模拟器上即時更新代碼。這本質上意味着在開發應用時,你不必浪費寶貴的時間來等待應用重新開機,并是以而中途放棄這些應用的狀态記錄。總之特别棒!

說明一下,我在 zeoturnaround 公司工作,也就是創造jrebel for android的公司。但它真的很好用,你值得一試。

android studio 2.0附帶的新模拟器用着也很爽。現在,mainactivity 類的模拟器螢幕被激活了。

點一下浮動按鈕,出現 snackbar。看起來不錯。讓我們随意更改一段代碼,檢驗一下代碼重新加載的功能。筆者首先想到的是修改 snackbar 的字元串值。

注意看,我們儲存了一個檔案,點選了一下按鈕,接着模拟器上的代碼就重新加載了。現在一切就緒!也就是說,我們可以研究 retrofit 2 到底有什麼用處了。

retrofit 2 是一個類型安全的 http 用戶端,适用于安卓(及 java)。但首先,它也是一個庫。是以我們要先聲明依賴。這個容易。不過,請注意,我們需要顯式依賴gson 轉換器,将 json 應答轉換為 model 類。這與retrofit 1不同。是以需要注意一下。

add these two lines to the build.gradle file:

将這兩行代碼加到 build.gradle 檔案中去:

retrofit 的主要功能是可以在運作時生成代碼,發送 http服務查詢請求。開發者隻需寫一個“說明”接口即可。假設我們有如下的一個 model 類:

通過這個我們可以建立一個名為githubservice的接口,用于實作 http 通信。

this is the simplest example, we add the @get annotation on an interface method and provide the path part of the url that we want to expose it on. conveniently, the method parameters can be referenced in the path string so you won’t need to jump through hoops to set those. additionally, with other annotations you can specify query parameters, post request body and so on:

@query(“key”) — for get request query parameter

@querymap — for the map of parameters

@body — use it with the @post annotation to provide the query body content.

這是一個最簡單的例子。我們在接口方法中加入 @get 注解,并且提供想要展示的 url 的path部分。友善的是,由于可以在 path 字元串中引用方法參數,是以我們無需跳出循環再重新設定。另外,通過這些注解,你可以設定查詢參數,以及 post 請求主體等等:

@query(“key”)  -- 用于get請求查詢參數

@querymap -- 用于參數映射

@body -- 與@post注解一起使用,提供查詢主體内容

下面,為了能在運作時使用這個接口,我們需要建構一個 retrofit 對象:

筆者傾向于在包含網站請求的接口内使用 retrofit builder。這麼做并不是想讓它變得複雜難懂。而是處于通用配置的考慮。例如,我們有預設的轉換器,将 json 響應對象轉為 java 對象,但是,即使在每個 service 中複制粘貼一遍,也好過使用單一的抽象類,後者很容易造成洩漏。

with these pieces in place, we just need to perform the network call:

the specification of our queries

the retrofit object builder

準備好這些代碼後,我們隻需發出網絡請求:

請求的說明

retrofit對象builder

為了實作githubservice接口,需要初始化一個用于執行 http 查詢請求的 call 對象。

另外,有人可能也會選擇設定請求的時間,讓它成為異步請求,同時在執行完畢後提供 callback。

聽起來超簡單!我們來處理一下 ui,然後寫入代碼。在浮動按鈕的應用模闆下,我們需要修改 content_main.xml 檔案。筆者添加了一個發起請求查詢的按鈕,以及一個用以顯示請求結果的文本區域:

第一次執行時,你的網絡請求代碼看起來可能是這樣的:

這段代碼自然無法運作。安卓架構不允許使用者在 ui 線程中執行網絡請求。ui 線程隻應該用來處理一些使用者輸入。在這個線程中執行任何引起長時間阻塞的操作都會讓使用者體驗變得非常糟糕。

是以,我們需要重構這段代碼,把網絡請求移入背景線程。使用 jrebel for android 可以不費任何時間就搞定這事。我們将代碼提取到 asynctask -- 這是一個在安卓上運作大型運算的預設架構。asynctask不太好看,它的具體運作方式也不算清潔,例如每次我們點選按鈕時它都會去建立一個 retrofit 對象。但是能用就行。

接着,從 eventlistener 中調用它:

好啦,現在代碼可以運作了。文本視圖會根據 http 請求的結果實時重新整理。

如何用 Retrofit 2 在安卓上實作 HTTP 通路?

現在,這個架構應用程式已經完成了,代碼順利建構并運作完畢。你可以自己去試試 retrofit和jrebel for android 。随意修改一些代碼,檢查一下新代碼構成的應用程式運作效果如何,也不會浪費任何時間。嘗試為 contributor 類增加幾個區域,替換 contributor 元件的 文本視圖,更改 http 的端點,将請求發往另一個站點。一切盡在你掌握!

在本文中,我們了解了如何使用 retrofit 2 建立一個發送網絡請求的簡易架構應用程式。程式的代碼可以在 github 上找到。對本文的最佳使用方式是,将它看作一篇快速指導,根據你的側重點寫一段自己的代碼,接着複制這個應用程式的代碼,導入 android studio,然後試試你自己的代碼吧!

今後,筆者會擴充這個架構應用程式,加入一些依賴注入架構,把ui代碼與其他代碼區分開來,以及使用rxandroid來響應式處理一些網絡請求等等。另外,你在安卓項目中預設使用的庫是哪一個?研究一下這個問題也許也會很有意思呢!在twitter上聯系我:@shelajev。期待與你們互動!

本文轉自 oneapm 官方部落格