Android 最好用的網絡庫 Retrofit

低吟不作語 2022-01-08 04:54:28 阅读数:417

android 最好 好用 retrofit

Retrofit 同樣是一款由 Square 公司開發的網絡庫,更側重於對上層接口的封裝


基本用法

通常,服務器提供的接口是按功能歸類的,比如新增用戶、修改用戶數據、查詢用戶數據等可以歸為一類,上架圖書,查詢在架圖書等又可以歸為一類。這樣的歸類能讓代碼結構變得更加合理,提供可閱讀性和可維護性

Retrofit 的用法就是基於以上幾點設計的,我們可以對服務器接口進行歸類,將功能同屬一類的服務器接口定義到同一個接口文件中,從而讓代碼結構變得更加合理

最後,我們無需關心網絡通信的細節,只需在接口文件中聲明一系列方法和返回值,然後通過注解的方式指定該方法對應哪個服務器接口,以及需要提供哪些參數。當我們在程序調用該方法時,Retrofit 會自動向對應的服務器接口發起請求,並將響應數據解析成返回值聲明的類型

要想使用 Retrofit,我們需要在項目中添加必要的依賴庫。編輯 app/build.gradle 文件,在 dependencies 閉包中添加如下內容:

dependencies {

...
implementation 'com.squareup.retrofit2:retrofit:2.6.1'
implementation 'com.squareup.retrofit2:converter:2.6.1'
}

上述第二條依賴是 Retrofit 的轉換庫,借助 GSON 來解析 JSON 數據。由於 Retrofit 會借助 GSON 將 JSON 數據轉換對象,因此這裏需要新增一個 App 類,並加入 id、name 和 version 三個字段

class App (val id: String, val name: String, val version: String)

接下來,我們可以根據服務器接口的功能進行歸類,創建不同種類的接口文件,並在其中定義對應具體服務器接口的方法

interface AppService {

// 發起一條 Get 請求,傳入參數是請求地址的相對路徑
// 返回值是 Retrofit 內置的 Call 類型,通過泛型來指定服務器響應的數據應該轉換為什麼對象
@GET("get_data.json")
fun getAppData(): Call<List<App>>
}

​ 編寫一個按鈕點擊事件,處理具體的網絡請求邏輯

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button.setOnClickListener {

val retrofit = Retrofit.Builder()
.baseUrl("http://127.0.0.1") // 指定所有 Retrofit 請求的根路徑
.addConverterFactory(GsonConverterFactory.create()) // 指定 Retrofit 在解析數據時使用的轉換庫
.build() // 構建 Retrofit 對象
val appService = retrofit.create(AppService::class.java)
// 調用 AppService 的 getAppData() 方法,返回 Call<List<App>>
// 再調用 enqueue() 方法,Retrofit 會根據注解中配置的服務器接口地址進行網絡請求
// 當發起請求時,Retrofit 會自動在內部開啟子線程,服務器響應的數據會回調到 Callback 實現裏面
appService.getAppData().enqueue(object : Callback<List<App>> {

override fun onResponse(call: Call<List<App>>, response: Response<List<App>>) {

val list = response.body()
if (list != null) {

for (app in list) {

Log.d("MainActivity", "id is ${
app.id}")
Log.d("MainActivity", "name is ${
app.name}")
Log.d("MainActivity", "version is ${
app.version}")
}
}
}
override fun onFailure(call: Call<List<App>>, t: Throwable) {

t.printStackTrace()
}
})
}
}
}

處理複雜的接口地址類型

服務器不可能總是提供靜態類型的接口,很多場景下,接口地址中的部分內容是會動態變化的,比如如下的接口地址:GET http://example.com/<page>/get_data.json,這種接口地址對應到 Retrofit 中該怎麼寫呢?

interface AppService {

@GET("{page}/get_data.json")
fun getData(@Path("page") page: Int): Call<Date>
}

<page> 部分代錶頁數,使用一個 {page} 的占比特符,又在 getData() 方法添加一個 page 參數,使用 @Path("page") 注解聲明這個參數

針對這種接口:GET http://example.com/get_data.json?u=<user>$t=<token>,Retrofit 專門提供了一種語法支持

interface AppService {

@GET("get_data.json")
fun getData(@Query("u") user: String, @Query("t") token: String): Call<Data>
}

除了 GET 請求,常用的還有 POST 請求,如果我們需要向服務器提交數據該怎麼寫呢?

POST http://example.com/data/create
{"id": 1, "content": "The description for this data"}

使用 POST 請求來提交數據,需要將數據放到 HTTP 請求的 body 部分,這個功能在 Retrofit 中可以借助 @Body 注解來完成

interface AppService {

@POST("/data/create")
fun createData(@Body data: Data): Call<ResponseBody>
}

有些服務器接口還會要求我們在 HTTP 請求的 header 中指定參數

interface AppService {

@Headers("User-Agent: okhttp", "Cache-Control: max-age=0")
@GET("get_data.json")
fun getData(): Call<Data>
}

以及動態指定 header 的值

interface AppService {

@GET("get_data.json")
fun getData(@Header("User-Agent") userAgent: String,
@Header("Cache-Control") cacheControl: String): Call<Data>
}

版权声明:本文为[低吟不作語]所创,转载请带上原文链接,感谢。 https://gsmany.com/2022/01/202201080454281256.html