前言
才發(fā)現(xiàn)已經(jīng)有一個月沒更新博客了尺迂,上個月發(fā)布了兩篇Chat:
都是高質(zhì)量的內(nèi)容和技術(shù)分享冒掌,所以占用了比較多的時間噪裕,感興趣的朋友可以支持一下我的創(chuàng)作,十分感謝~
今天準備跟大家分享一下Retrofit的用法和源碼的實現(xiàn)原理股毫。Retrofit是對Okhttp的二次封裝的開源庫膳音,目的是讓okhttp使用起來更方便,更簡潔铃诬,通過注解等信息封裝成Okhttp請求祭陷,完成整個網(wǎng)絡(luò)請求的過程,現(xiàn)在已經(jīng)是非常流行的框架之一趣席,是我們技術(shù)學(xué)習(xí)之路的必選內(nèi)容兵志。
Okhttp源碼分析博客地址:https://blog.csdn.net/u011315960/article/details/80017877
源碼地址:Retrofit的github地址
正文
首先我們回顧一下Retrofit的用法:
首先需要定義我們的接口文件,這個類必須是接口類型:
/**
* Created by li.zhipeng on 2018/8/29.
*/
public interface TestApi {
/**
* 模擬GET一個數(shù)據(jù)請求
*/
@GET
ResponseWrapper getData(@Url String url);
/**
* 模擬POST一個數(shù)據(jù)請求
*/
@POST
@FormUrlEncoded
ResponseWrapper postData(@Url String url, @Field("wd") String key);
}
非常簡單的get請求宣肚,我們需要指定請求的類型@Get想罕,@POST钉寝,@PUT等等弧呐,這寫請求類型的注解可以設(shè)置網(wǎng)絡(luò)請求的相對地址闸迷。如果有參數(shù),還可以指定網(wǎng)絡(luò)請求的參數(shù)俘枫,通過@Field(“paramName”)腥沽,注解內(nèi)的value是提交的參數(shù)對應(yīng)的key。
有些用過Retrofit的朋友可能會問:為什么你的返回類型是ResponseWrapper今阳?
其實這是我通過Retrofit的api指定的返回的類型盾舌,我們可以按照自己的需要指定任何類型蘸鲸。
接下來初始化Retrofit的配置信息,并解析定義的接口文件:
val retrofit = Retrofit.Builder()
// 必填項
.baseUrl("http://www.baidu.com")
.client(OkHttpClient())
// 對得到的結(jié)果進行轉(zhuǎn)換膝舅,常用的有加密解密仍稀,json轉(zhuǎn)換等等
.addConverterFactory(StringConvertFactory())
// 對返回的結(jié)果進行封裝埂息,常用的有之間轉(zhuǎn)化成Rxjava對象
// 這里我們簡單的進行包裝
.addCallAdapterFactory(ResponseWrapperCallAdapterFactory())
.build()
api = retrofit.create(TestApi::class.java)
baseUrl:請求的基礎(chǔ)地址千康,如果沒有參數(shù)中沒有指定@Url地址,真實的網(wǎng)絡(luò)地址是baseUrl + @GET注解的value相對地址琉闪。
client:發(fā)起網(wǎng)絡(luò)請求的OkhttpClient對象颠毙。
addConverterFactory:添加網(wǎng)絡(luò)請求的轉(zhuǎn)換工廠類砂碉,可以處理網(wǎng)絡(luò)請求過程中Request或者Response,例如可以把Response中的數(shù)據(jù)流轉(zhuǎn)換成字符串滴某。
addCallAdapterFactory:設(shè)置網(wǎng)絡(luò)請求的返回類型霎奢。demo中直接返回自定義的ResponseWrapper,所以剛剛的接口文件返回的類型就只能是ResponseWrapper帝美。
接下來看看我自定義的StringConvertFactory:
/**
* Created by li.zhipeng on 2018/8/29.
*
* 把得到的數(shù)據(jù)response轉(zhuǎn)換成String
*/
public class StringConvertFactory extends Converter.Factory {
@Override
public Converter<ResponseBody, String> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
return new Converter<ResponseBody, String>() {
@Override
public String convert(@NonNull ResponseBody value) throws IOException {
return value.string();
}
};
}
}
很簡單悼潭,把response的內(nèi)容取出來舞箍,返回String字符串。
再看看ResponseWrapperCallAdapterFactory:
/**
* Created by li.zhipeng on 2018/8/29.
*
* 把得到網(wǎng)絡(luò)請求結(jié)果String占拍,轉(zhuǎn)換成ResponseWrapper
*/
public class ResponseWrapperCallAdapterFactory extends CallAdapter.Factory {
@Override
public CallAdapter<String, ResponseWrapper> get(@NonNull final Type returnType, @NonNull Annotation[] annotations, @NonNull Retrofit retrofit) {
return new CallAdapter<String, ResponseWrapper>() {
@Override
public Type responseType() {
return returnType;
}
@Override
public ResponseWrapper adapt(@NonNull Call<String> call) {
try {
return new ResponseWrapper(call.execute().body());
} catch (IOException e) {
e.printStackTrace();
}
return new ResponseWrapper("error");
}
};
}
}
這里主要是實現(xiàn)adapt方法刷喜,對返回值類型進行轉(zhuǎn)換立砸,這里ResponseWrapper就是一個包裝類颗祝,把得到的String保存起來螺戳。值得注意的是折汞,我們在這里直接發(fā)起了同步的網(wǎng)絡(luò)請求,所以別忘了實際使用中损同,不能在主線程發(fā)起網(wǎng)絡(luò)請求鸟款。
看一下沒什么卵用的ResponseWrapper:
/**
* Created by li.zhipeng on 2018/8/29.
* <p>
* 網(wǎng)絡(luò)請求包裝類
*/
public class ResponseWrapper {
public String response;
public ResponseWrapper(String response) {
this.response = response;
}
}
最后在MainActivity中發(fā)起網(wǎng)絡(luò)請求:
Thread {
val result = api.postData("www.baidu.com", "111").response
runOnUiThread {
val textView = findViewById<TextView>(R.id.textView)
textView.text = result
}
}.start()
看一下運行結(jié)果:
我們已經(jīng)得到了請求的數(shù)據(jù)组哩,Retrofit的基礎(chǔ)使用就是這些,當然還有其他的api蛛砰,這里簡單介紹一下:
callFactory: 跟client一樣暴备,指定運行Okhttp網(wǎng)絡(luò)請求的工廠類们豌,OkhttpClient已經(jīng)實現(xiàn)了Factory中的方法。
callAdapterFactories:同時設(shè)置多個CallAdapterFactoty障癌。
converterFactories:同時設(shè)置多個ConvertFactoty.
callbackExecutor:執(zhí)行callback的線程池涛浙,用的很少摄欲。Android默認是主線程。
validateEagerly:是否一次在創(chuàng)建接口文件代理時我注,解析所有的接口方法迟隅。
總結(jié)
本來想把基礎(chǔ)使用和源碼解析寫成一篇,考慮一下還是分開吧奔缠,誰也不愿意看又臭又長的長篇大論校哎,所以下一篇繼續(xù)分析:Retrofit的源碼瞳步。