介紹
Retrofit是什么
retrofit:改進(jìn)瞻惋、翻新的意思厦滤。
Square 公司著名的開源項(xiàng)目之一。
Retrofit這個(gè)項(xiàng)目是一個(gè) RESTful 的 HTTP 網(wǎng)絡(luò)請(qǐng)求框架的封裝歼狼。
為什么說它使網(wǎng)絡(luò)請(qǐng)求框架的封裝掏导?
主要原因在于網(wǎng)絡(luò)請(qǐng)求的工作并不是 Retrofit 來完成的
Retrofit 2.0 開始內(nèi)置 OkHttp,前者專注于接口的封裝蹂匹,后者專注于網(wǎng)絡(luò)請(qǐng)求的高效碘菜,二者分工協(xié)作。
我們的應(yīng)用程序通過 Retrofit 請(qǐng)求網(wǎng)絡(luò),實(shí)際上是使用 Retrofit 接口層封裝請(qǐng)求參數(shù)忍啸、Header仰坦、Url 等信息,之后由 OkHttp 完成后續(xù)的請(qǐng)求操作计雌;在服務(wù)端返回?cái)?shù)據(jù)之后悄晃,OkHttp 將原始的結(jié)果交給 Retrofit,后者根據(jù)用戶的需求對(duì)結(jié)果進(jìn)行解析的過程凿滤。
所以說妈橄,所謂 Retrofit,其實(shí)就是 Retrofitting OkHttp 翁脆。
使用
原理解析
Retrofit這個(gè)框架的實(shí)現(xiàn)主要使用了哪些技術(shù)呢眷蚓?
我覺得核心的就兩個(gè):動(dòng)態(tài)代理、注解
-
動(dòng)態(tài)代理
動(dòng)態(tài)代理可以理解成是雙層靜態(tài)代理反番,表面是A代理了B沙热,其實(shí)是A將調(diào)用轉(zhuǎn)發(fā)給C,C再將調(diào)用轉(zhuǎn)發(fā)給B罢缸。
開發(fā)者需要提供一個(gè)實(shí)現(xiàn)了InvocationHandler的子類 C篙贸。用戶直接調(diào)用代理類 A 的對(duì)象,A 將調(diào)用轉(zhuǎn)發(fā)給委托類 C枫疆,委托類 C 再將調(diào)用轉(zhuǎn)發(fā)給它的委托類 B爵川。
舉個(gè)栗子
public class Main {
public static void main(String[] args) {
// create proxy instance
TimingInvocationHandler timingInvocationHandler = new TimingInvocationHandler(new OperateImpl());
Operate operate = (Operate)(Proxy.newProxyInstance(Operate.class.getClassLoader(), new Class[] {Operate.class}, timingInvocationHandler));
// call method of proxy instance
operate.operateMethod1();
System.out.println();
operate.operateMethod2();
System.out.println();
operate.operateMethod3();
}
}
A:Porxy.newProxyInstance()生成的代理類
C:TimingInvocationHandler對(duì)象
B:OperateImpl對(duì)象
使用動(dòng)態(tài)代理的關(guān)鍵就是中間的C,like this
public class TimingInvocationHandler implements InvocationHandler {
private Object target;
public TimingInvocationHandler() {}
public TimingInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long start = System.currentTimeMillis();
Object obj = method.invoke(target, args);
System.out.println(method.getName() + " cost time is:" + (System.currentTimeMillis() - start));
return obj;
}
}
proxy:通過 Proxy.newProxyInstance() 生成的代理類對(duì)象
method:代理對(duì)象被調(diào)用的函數(shù)
args:表示代理對(duì)象被調(diào)用的函數(shù)的參數(shù)息楔。
被代理的類(即委托類)以及相應(yīng)的接口
public interface Operate {
public void operateMethod1();
public void operateMethod2();
public void operateMethod3();
}
public class OperateImpl implements Operate {
@Override
public void operateMethod1() {
System.out.println("Invoke operateMethod1");
sleep(110);
}
@Override
public void operateMethod2() {
System.out.println("Invoke operateMethod2");
sleep(120);
}
@Override
public void operateMethod3() {
System.out.println("Invoke operateMethod3");
sleep(130);
}
private static void sleep(long millSeconds) {
try {
Thread.sleep(millSeconds);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
- 注解
不說了
好寝贡,現(xiàn)在進(jìn)入正題,關(guān)于Retrofit的原理解析
Retrofit對(duì)象的create()方法钞螟,其內(nèi)部實(shí)現(xiàn)就是通過Porxy.newProxyInstance()來創(chuàng)建代理對(duì)象
作者:騰訊Bugly
鏈接:https://zhuanlan.zhihu.com/p/24109629
來源:知乎
著作權(quán)歸作者所有兔甘。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處鳞滨。
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(service);
}
//這里返回一個(gè) service 的代理對(duì)象
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
private final Platform platform = Platform.get();
@Override
public Object invoke(Object proxy, Method method, Object... args) throws Throwable {
// If the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
//DefaultMethod 是 Java 8 的概念洞焙,是定義在 interface 當(dāng)中的有實(shí)現(xiàn)的方法
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
//每一個(gè)接口最終實(shí)例化成一個(gè) ServiceMethod,并且會(huì)緩存
ServiceMethod serviceMethod = loadServiceMethod(method);
//由此可見 Retrofit 與 OkHttp 完全耦合拯啦,不可分割
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
//下面這一句當(dāng)中會(huì)發(fā)起請(qǐng)求澡匪,并解析服務(wù)端返回的結(jié)果
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
之后,就可以在代理對(duì)象身上去調(diào)用的接口定義的那些方法了褒链。
都知道唁情,代理對(duì)象可以對(duì)原本委托對(duì)象的方法進(jìn)行增強(qiáng),附加更多的功能甫匹。
而對(duì)于Retrofit來講甸鸟,代理對(duì)象就是給原本委托對(duì)象中相應(yīng)的方法增加網(wǎng)絡(luò)請(qǐng)求獲取的功能惦费,這個(gè)功能具體由誰來做呢,由OkHttp來做抢韭。
我們已經(jīng)看到 Retrofit 為我們構(gòu)造了一個(gè) OkHttpCall 薪贫,實(shí)際上每一個(gè) OkHttpCall 都對(duì)應(yīng)于一個(gè)請(qǐng)求,它主要完成最基礎(chǔ)的網(wǎng)絡(luò)請(qǐng)求刻恭,而我們?cè)诮涌诘姆祷刂锌吹降?Call 默認(rèn)情況下就是 OkHttpCall 了瞧省,如果我們添加了自定義的 callAdapter,那么它就會(huì)將 OkHttp 適配成我們需要的返回值鳍贾,并返回給我們鞍匾。