<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
Retrofit是目前Android平臺上比較流行的網路請求框架之一,它提供了一種簡潔、靈活的方式來處理HTTP請求和響應。Retrofit的設計目的是使網路請求的程式碼更加容易編寫和閱讀,同時還提供了許多有用的特性,如註解解析、動態代理等。在本文中,我們將對Retrofit的註解解析和動態代理進行詳細的分析。
在使用Retrofit時,我們通常會定義一個介面,該介面用於描述我們要請求的API介面。在這個介面中,我們可以使用註解來描述API的各個方面,如HTTP方法、請求URL、請求引數等。Retrofit會根據這些註解來生成相應的網路請求程式碼。下面是一個範例:
interface GitHubService { @GET("users/{user}/repos") fun listRepos(@Path("user") user: String): Call<List<Repo>> }
在這個範例中,@GET註解表示這是一個HTTP GET請求,"users/{user}/repos"表示請求的URL,@Path(“user”)表示請求URL中的引數。Retrofit會解析這些註解,並生成相應的網路請求程式碼。
Retrofit中的註解解析是通過Retrofit.Builder中的retrofit2.Retrofit#create方法實現的。這個方法會返回一個代理物件,該代理物件會在呼叫介面方法時解析註解並生成相應的網路請求。
下面是retrofit2.Retrofit#create方法的核心程式碼:
public <T> T create(final Class<T> service) { Utils.validateServiceInterface(service); if (validateEagerly) { eagerlyValidateMethods(service); } 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 (method.getDeclaringClass() == Object.class) { return method.invoke(this, args); } if (platform.isDefaultMethod(method)) { return platform.invokeDefaultMethod(method, service, proxy, args); } ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method); OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args); return serviceMethod.callAdapter.adapt(okHttpCall); } }); }
該方法首先會驗證介面是否滿足要求,然後會返回一個代理物件。這個代理物件實現了介面中的所有方法,並在呼叫方法時解析註解並生成相應的網路請求。
我們可以看到,代理物件的實現是通過java.lang.reflect.Proxy類實現的。Proxy.newProxyInstance方法會返回一個代理物件,該代理物件實現了指定介面中的所有方法。當我們呼叫代理物件的方法時,代理物件會呼叫InvocationHandler.invoke方法,該方法中實現了註解解析和網路請求的生成。
在InvocationHandler.invoke方法中,首先會判斷是否呼叫了Object類的方法,如果是,則直接返回該方法的執行結果。如果不是,則進一步判斷是否呼叫了介面的預設方法,如果是,則使用Platform類呼叫預設方法。否則,就呼叫loadServiceMethod方法來解析註解並生成網路請求。
loadServiceMethod方法會首先從快取中獲取ServiceMethod物件,如果快取中沒有,則建立一個新的ServiceMethod物件。ServiceMethod物件包含了網路請求的相關資訊,如HTTP方法、請求URL、請求引數等。ServiceMethod物件的建立是通過ServiceMethod.Builder類實現的,該類會解析介面方法上的註解並生成相應的網路請求。
下面是ServiceMethod.Builder類的核心程式碼:
public ServiceMethod build() { callAdapter = createCallAdapter(); responseType = callAdapter.responseType(); if (responseType == Response.class || responseType == okhttp3.Response.class) { throw methodError("'" + Utils.getRawType(responseType).getName() + "' is not a valid response body type. Did you mean ResponseBody?"); } responseConverter = createResponseConverter(); RequestFactory requestFactory = createRequestFactory(); return new ServiceMethod<>(requestFactory, callAdapter, responseConverter); }
在ServiceMethod.Builder類中,首先會建立一個CallAdapter物件,該物件用於處理網路請求的結果。然後會檢查responseType是否是Response或okhttp3.Response型別,如果是,則丟擲異常。接下來,會建立一個ResponseConverter物件,該物件用於將網路請求的結果轉換成Java物件。最後,會建立一個RequestFactory物件,該物件用於建立okhttp3.Request物件。
ServiceMethod物件包含了網路請求的相關資訊,包括RequestFactory物件、CallAdapter物件和ResponseConverter物件。OkHttpCall物件則負責執行網路請求,並將結果傳遞給CallAdapter物件進行處理。CallAdapter物件最終將結果轉換成Java物件並返回給呼叫者。
在前面的程式碼中,我們已經看到了動態代理的使用。在Retrofit中,我們使用動態代理來實現註解解析和網路請求的生成。動態代理是一種機制,通過它我們可以在執行時建立一個代理物件,該代理物件會代替原始物件來執行方法呼叫。
在Retrofit中,我們使用動態代理來建立一個實現介面的代理物件。當我們呼叫代理物件的方法時,代理物件會呼叫InvocationHandler.invoke方法,該方法中實現了註解解析和網路請求的生成。因此,我們可以將網路請求的程式碼封裝在介面中,使得我們的程式碼更加簡潔和易於閱讀。
下面是一個使用動態代理的簡單範例:
import java.lang.reflect.* interface HelloWorld { fun sayHello() } class HelloWorldImpl : HelloWorld { override fun sayHello() { println("Hello, world!") } } fun main() { val proxy = Proxy.newProxyInstance( DynamicProxyExample::class.java.classLoader, arrayOf(HelloWorld::class.java), object : InvocationHandler { private val target: HelloWorld = HelloWorldImpl() override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any? { println("Before method execution...") val result = method?.invoke(target, *(args ?: emptyArray())) println("After method execution...") return result } } ) as HelloWorld proxy.sayHello() }
在這個範例中,我們定義了一個HelloWorld
介面和一個HelloWorldImpl
實現類。然後,我們使用動態代理建立了一個代理物件,該代理物件實現了HelloWorld
介面。在InvocationHandler
的invoke
方法中,我們首先輸出一行紀錄檔,然後呼叫HelloWorldImpl
物件的sayHello
方法,最後再輸出一行紀錄檔。當我們呼叫代理物件的sayHello
方法時,代理物件會呼叫InvocationHandler.invoke
方法,從而實現了在方法執行前後輸出紀錄檔的功能。動態代理是一種非常強大的機制,可以用於實現很多功能,如效能分析、紀錄檔記錄、事務管理等。在Retrofit中,我們使用動態代理來實現註解解析和網路請求的生成,從而使得我們的程式碼更加簡潔和易於閱讀。
到此這篇關於Retrofit網路請求框架之註解解析和動態代理的文章就介紹到這了,更多相關Retrofit註解解析和動態代理內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45