前言
?目前Retrofit2值戳、RxJava2西篓、OkHttp3可以說(shuō)非秤冢火,經(jīng)常被一并提及岂津,因此學(xué)習(xí)它們是非常有必要的虱黄。
?本系列主要寫Retrofit2的使用,Retrofit2其實(shí)并不復(fù)雜寸爆,使用它只是為了規(guī)范我們網(wǎng)絡(luò)請(qǐng)求的代碼礁鲁,深入學(xué)習(xí)之后會(huì)發(fā)現(xiàn)Retrofit2可以讓代碼可讀性更好盐欺。
?Retrofit的特點(diǎn)就是使用注解來(lái)描述一個(gè)http請(qǐng)求,本系列會(huì)在下一章具體講解每一個(gè)注解的使用仅醇。
?retrofit官網(wǎng)地址:https://square.github.io/retrofit/
1 入門
?GRADLE
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
?也可以在官網(wǎng)下載JAR包冗美,GitHub上可以查看源代碼和示例。
?①創(chuàng)建實(shí)體類接收J(rèn)son析二。
data class WordData constructor(var reason:String,var result:Any,var error_code:String)
?②將HTTP API轉(zhuǎn)換成接口粉洼,如下所示:
interface WordService{
@GET("query")
fun getWord(@Query("word") word: String, @Query("dtype") dtype: String,@Query("key") key: String): Call<WordData>
}
?③生成Retrofit實(shí)現(xiàn)接口實(shí)例。
var retrofit = Retrofit.Builder()
.baseUrl("http://v.juhe.cn/xhzd/")
.addConverterFactory(GsonConverterFactory.create())
.build()
var wordService = retrofit.create(WordService::class.java)
?④調(diào)用接口的方法去異步請(qǐng)求網(wǎng)絡(luò)叶摄,并通過(guò)callback回調(diào)請(qǐng)求結(jié)果属韧。
? (示例使用的是聚合數(shù)據(jù)的免費(fèi)接口,key是錯(cuò)誤的蛤吓,正確key的Json太長(zhǎng)....)
wordService.getWord("你","json","c5c6a09be5cdb2047")
.enqueue(object : Callback<WordData> {
override fun onFailure(call: Call<WordData>, t: Throwable) {
Log.d(tag,"onFailure")
}
override fun onResponse(call: Call<WordData>, response: Response<WordData>) {
Log.d(tag,response.body().toString())
}
})
?請(qǐng)求回來(lái)的數(shù)據(jù)如下所示:
WordData(reason=錯(cuò)誤的請(qǐng)求KEY, result=null, error_code=10001)
?至此宵喂,已經(jīng)使用Retrofit完成一個(gè)網(wǎng)絡(luò)請(qǐng)求。
?你也可以通過(guò)call調(diào)用同步網(wǎng)絡(luò)請(qǐng)求代碼如下所示:
var wordService = wordService.getWord("你","json","c5c6a09be5cdb2047")
var wordData = wordService.execute().body() as WordData
2 Converters
?retrofit可以配置不同的工具來(lái)解析數(shù)據(jù)会傲,例如gson锅棕、xml等等。
-
Gson:
com.squareup.retrofit2:converter-gson
-
Simple XML:
com.squareup.retrofit2:converter-simplexml
?示例代碼如下所示:
var retrofit = Retrofit.Builder()
.baseUrl("http://v.juhe.cn/xhzd/")
.addConverterFactory(GsonConverterFactory.create())
.build()
?通過(guò)調(diào)用addConverterFactory()方法淌山,添加GsonConverterFactory裸燎。
3 OkHttpClient
?Retrofit也可以自定義OkHttpClient,代碼如下所示:
val dispatcher = Dispatcher(Executors.newFixedThreadPool(20))
dispatcher.setMaxRequests(20)
dispatcher.setMaxRequestsPerHost(1)
val okHttpClient = OkHttpClient.Builder()
.dispatcher(dispatcher)
.connectionPool(ConnectionPool(100, 30, TimeUnit.SECONDS))
.build()
var retrofit = Retrofit.Builder()
.baseUrl("http://v.juhe.cn/xhzd/")
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)
.build()
4 Retrofit2 + RxJava2
?在Retrofit中使用RxJava2泼疑,接口的定義和網(wǎng)絡(luò)請(qǐng)求和上面略有不同德绿,而且需要調(diào)用addCallAdapterFactory添加對(duì)RxJava2的支持。
Retrofit2
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
Rxjava2
implementation 'io.reactivex.rxjava2:rxjava:2.2.3'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
①將HTTP API轉(zhuǎn)換成接口退渗,但是返回參數(shù)需要改變成Observable<WordData>移稳,如下所示:
interface WordService {
@GET("/xhzd/query")
fun getWord(@Query("word") word: String, @Query("dtype") dtype: String,@Query("key") key: String): Observable<WordData>
}
②調(diào)用addCallAdapterFactory方法傳入RxJava2CallAdapterFactory.create()生成Retrofit,然后實(shí)現(xiàn)接口實(shí)例氓辣。
var retrofit = Retrofit.Builder()
.baseUrl("http://v.juhe.cn")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(okHttpClient)
.build()
var wordService = retrofit.create(WordService::class.java)
③使用RxJava2對(duì)數(shù)據(jù)進(jìn)行處理秒裕,代碼如下所示:
wordService.getWord("你", "json", "c5c6a09be5cdb2047")
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
Log.d(tag, it.toString())
}, {
Log.d(tag, "onFailure")
})
可以看見(jiàn)日志輸入如下所示:
WordData(reason=錯(cuò)誤的請(qǐng)求KEY, result=null, error_code=10001)
5 高級(jí)寫法
①首先使用Body定義Api
interface IApi {
@POST("/xhzd/getUnreadRemind")
fun getMessageRemind(@Body params: JsonObject?): Observable<BaseBean<RedPointBean>>
}
②然后可以使用JsonObject定義一個(gè)基礎(chǔ)請(qǐng)求體袱蚓,封裝一些我們每次請(qǐng)求都會(huì)帶的參數(shù)钞啸。
object BaseRequestParams {
fun basePostParams(): JsonObject {
val baseParams = JsonObject()
baseParams.addProperty("device_id", DeviceUtil.getDeviceIMEI(getApplication()))
baseParams.addProperty("platform", "android")
return baseParams
}
}
③最后進(jìn)行請(qǐng)求
var mService = retrofit.create(IApi::class.java)
override fun getSearchRecommendWord(keyword: String): Observable<BaseBean<RecommendWordBean>> {
val params = BaseRequestParams.basePostParams()
params.addProperty("keyword", keyword)
return mService.getMessageRemind(params)
}
總結(jié)
?Retrofit使用非常簡(jiǎn)單,首先轉(zhuǎn)換接口喇潘,然后創(chuàng)建Retrofit實(shí)例体斩,再實(shí)現(xiàn)接口,最后進(jìn)行網(wǎng)絡(luò)請(qǐng)求颖低,回調(diào)處理數(shù)據(jù)絮吵。