Retrofit官方文檔java
在Maven中使用:git
<dependency>
<groupId>com.squareup.retrofit2</groupId>
<artifactId>retrofit</artifactId>
<version>2.9.0</version>
</dependency>
複製代碼
在Gradle中使用:github
// retrofit2依賴
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
// Gson依賴
implementation "com.squareup.retrofit2:converter-gson:2.5.0"
implementation "com.google.code.gson:gson:2.8.6"
// 日誌攔截器
implementation 'com.squareup.okhttp3:logging-interceptor:3.3.1'
複製代碼
注意:版本號可能會不同,具體到官網進行查找設計模式
將全部的接口方法都寫在這裏面markdown
由於Retrofit是經過Interface來管理HTTP API,並且這個接口不能繼承其餘接口網絡
public interface RemoteService {
/** * 網絡請求一個註冊接口 * * @param model RegisterModel * @return RspModel<AccountRspModel> */
@POST("account/register")
Call<RspModel<AccountRspModel>> accountRegister(@Body RegisterModel model);
}
複製代碼
在項目中,爲了不代碼冗餘,咱們常常會將網絡請求進行一個總體的封裝,以單例模式架構
/** * 網絡請求的封裝 * * @author : iwen大大怪 * @create : 12-7 007 18:19 */
public class Network {
// 單例模式
private static Network instance;
private OkHttpClient client;
private Retrofit retrofit;
static {
instance = new Network();
}
private Network() {
}
/** * 步驟1:構建一個Retrofit */
public static Retrofit getRetrofit() {
if (instance.retrofit != null){
return instance.retrofit;
}
// 步驟:2:獲得一個OkHttpClient
OkHttpClient client = new OkHttpClient.Builder()
// 跳過ssh檢查
.sslSocketFactory(OkHttpSSH.createSSLSocketFactory(), new OkHttpSSH.TrustAllCerts())
.connectTimeout(10, TimeUnit.SECONDS)// 設置超時時間
.writeTimeout(10, TimeUnit.SECONDS)// 設置寫入超時時間
.readTimeout(20, TimeUnit.SECONDS)// 設置讀取超時時間
// 給全部的請求添加一個攔截器(看具體需求)
//.addInterceptor()
.build();
// 步驟3:獲取Retrofit對象
Retrofit.Builder builder = new Retrofit.Builder();
instance.retrofit = builder
.baseUrl("根據須要填寫")
.client(client) // 設置client
.addConverterFactory(GsonConverterFactory.create()) // 設置數據解析器
.build();
return instance.retrofit;
}
/** * 步驟4:返回一個請求代理 * @return RemoteService */
public static RemoteService mRemoteService(){
// 傳入具體接口類,將其轉換成動態代理
return Network.getRetrofit().create(RemoteService.class);
}
}
複製代碼
RemoteService service = Network.mRemoteService();
// 調用具體接口請求的方法
Call<RspModel<LogoutRspModel>> call = service.accountRegister(model);
// 發起異步請求
call.enqueue(new Callback<RspModel<LogoutRspModel>>() {
@Override
public void onResponse(Call<RspModel<LogoutRspModel>> call, Response<RspModel<LogoutRspModel>> response) {
// 請求成功回調
}
@Override
public void onFailure(Call<RspModel<LogoutRspModel>> call, Throwable t) {
// 請求失敗回調
}
});
複製代碼
準確來講,Retrofit是一個RESTful的HTTP網絡請求框架的封裝。框架
**緣由:**網絡請求的工做本質仍是由OKHTTP完成,而Retrofit只是負責網絡請求接口的封裝。ssh
tempimg-1302248544.cos.ap-chengdu.myqcloud.com/Img/PingMu/…異步
請求前:
統一的配置網絡請求頭:使用建造者模式、門面模式來對一些參數進行統一的配置,而且將其保存。
一致適配請求request:create()方法裏面使用了動態代理模式,這樣子就能夠代理全部類對象。
請求後:
線程切換:
數據適配:
Retrofit這個類就是保存一系列的參數給後面使用,使用的是Build模式
在構建Retrofit時,採用的是建造者模式、外觀模式
在適配一致請求request時:Create()方法裏面使用了動態代理模式
靜態代理模式:
- 代理類和委託類有一樣的接口。
- 代理類主要負責爲委託類預處理消息、過濾消息、把消息轉發給委託類,以及過後的消息處理等。
- 一個代理類的對象與一個委託類的對象關聯,代理類的對象自己並不真正的實現服務,而是經過調用委託類的對象的相關方法,來提供服務。
動態代理模式:
代理類在程序運行前不存在、運行時由程序動態生成的代理方式稱爲動態代理。
傳進去咱們接口的類對象便可生成對應的實例並調用
具體方法
,是由於這裏面實際上retrofit利用動態代理模式生成了一個代理對象(而且實現了RemoteService),而後一旦調用了RemoteService的方法,就會觸發代理對象的invoke方法,從而在invoke總攔截並得到了RemoteService的全部方法以及對應的那些@GET
@POST
等Retrofit的註解信息,而後利用OKhttp完成真正的請求操做。
create(RemoteService.class);
複製代碼
這一行的時候,虛擬機內部生成了代理類的Class二進制流,而且加載到虛擬機中造成代理類的Class對象,再反射獲得代理類對象,而該代理類即實現了GitHubService,而且持有了InvocationHandler的引用。
咱們從Retrofit
的create
方法一探究竟:
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(service);
}
// 經過Proxy.newProxyInstance生成了代理類
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);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
複製代碼
能夠看到,也是經過Proxy.newProxyInstance
生成了代理類,並new了一個匿名內部InvocationHandler
對象,重寫它的invoke
方法,至關於經過咱們傳進來的接口,生成了一個接口的代理類,而且實現了接口是全部方法(由於InvocationHandler
的參數裏傳進去了new Class<?>[] { service }
),而後返回給外部。 外部一旦調用了接口方法,例如request.getData();
,就會觸發InvocationHandler
的invoke
,從而根據註解生成Retrofit的ServiceMethod
和OkHttpCall
對象,這些都是發起網絡請求的必備信息,而後最終發起請求。