Retrofit的簡(jiǎn)單使用
1. 添加依賴
implementation 'com.squareup.retrofit2:retrofit:2.6.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.6.0'
implementation 'com.squareup.retrofit2:converter-gson:2.6.0'
2. 創(chuàng)建一個(gè)interface作為Web Service的請(qǐng)求集合,在上面用注解寫(xiě)入需要配置的請(qǐng)求方法
interface GithubService {
@GET("/users/{user}/repos")
fun listRepos(@Path("user") user: String): Call<List<Repo>>
}
3. 獲取Retrofit實(shí)例(單例對(duì)象)
object Net {
fun instance() =
Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl("https://api.github.com/")
.build()
}
4. 創(chuàng)建出Service interface實(shí)例,調(diào)用對(duì)應(yīng)的接口方法,創(chuàng)建出相應(yīng)的可以用來(lái)發(fā)起網(wǎng)絡(luò)請(qǐng)求的Call對(duì)象
val githubService = Net.instance().create(GithubService::class.java)
val listRepos = githubService.listRepos("hsicen")
5. 使用Call.execute()或者Call.enqueue()發(fā)起請(qǐng)求
listRepos.enqueue(object : Callback<List<Repo>> {
override fun onFailure(call: Call<List<Repo>>, t: Throwable) {
tv_content.text = t.message
}
override fun onResponse(call: Call<List<Repo>>, response: Response<List<Repo>>) {
tv_content.text = response.body().toString()
}
})
Retrofit源碼分析
首先我們從離我們最近的位置作為切入點(diǎn)(通常是業(yè)務(wù)代碼的最后一行),這里我們點(diǎn)進(jìn)Call.enqueue(),看看里面的代碼邏輯
/**
* Asynchronously send the request and notify {@code callback} of its response or if an error
* occurred talking to the server, creating the request, or processing the response.
*/
void enqueue(Callback<T> callback);
發(fā)現(xiàn)這是一個(gè)接口,沒(méi)有具體實(shí)現(xiàn),切入失?。滑F(xiàn)在需要逐步回退尋找到下一個(gè)切入點(diǎn)Retrofit.create()
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service); //接口驗(yàn)證
if (validateEagerly) {eagerlyValidateMethods(service);} //提前驗(yàn)證所有方法的正確性,會(huì)用到反射
//動(dòng)態(tài)代理 創(chuàng)建一個(gè)運(yùn)行時(shí)的類,Interface的每一個(gè)方法調(diào)用都會(huì)交由InvocationHandler來(lái)處理
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },new InvocationHandler() {
private final Platform platform = Platform.get();
private final Object[] emptyArgs = new Object[0];
@Override public @Nullable Object invoke(Object proxy, Method method,@Nullable Object[] args) throws Throwable {
// If the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {//繼承自O(shè)bject的方法
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) { //接口默認(rèn)方法 Java8
return platform.invokeDefaultMethod(method, service, proxy, args);
}
//關(guān)鍵代碼
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
可以看到前面兩行是代碼健壯性驗(yàn)證,核心代碼是Proxy.newProxyInstance()方法來(lái)創(chuàng)建Service實(shí)例。這個(gè)方法會(huì)為參數(shù)中的Interface創(chuàng)建一個(gè)對(duì)象,這個(gè)對(duì)象實(shí)現(xiàn)了Interface的每個(gè)方法,并且每個(gè)方法的實(shí)現(xiàn)都會(huì)雷同的:調(diào)用對(duì)象實(shí)例內(nèi)部的一個(gè)InvocationHandler成員變量的invoke方法,并把自己的方法信息傳遞進(jìn)去。這樣就在實(shí)質(zhì)上實(shí)現(xiàn)了代理邏輯;Interface中的方法全部由一個(gè)另外設(shè)定的InvocationHandler對(duì)象來(lái)進(jìn)行代理操作。并且這些方法的具體實(shí)現(xiàn)是在運(yùn)行時(shí)生成Interface實(shí)例時(shí)才確定的,而不是在編譯時(shí)。這就是動(dòng)態(tài)代理機(jī)制,大致像下面這樣:
//GithubService.kt
interface GithubService {
@GET("/users/{user}/repos")
fun listRepos(@Path("user") user: String): Call<List<Repo>>
@GET("/users/hsicen")
fun getUser(): Call<User>
}
//realService
class RealService : GithubService {
private val invocationHandler = object : InvocationHandler {
private val platform = Platform.get();
override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any {
//扮演代理角色,對(duì)不同的方法做不同的處理
return Any()
}
}
override fun listRepos(user: String): Call<List<Repo>> {
val method = GithubService::class.java.getMethod("listRepos")
return invocationHandler.invoke(this, method, null) as Call<List<Repo>>
}
override fun getUser(): Call<User> {
val method = GithubService::class.java.getMethod("getUser")
return invocationHandler.invoke(this, method, null) as Call<User>
}
}
接下主要關(guān)注loadServiceMethod(method).invoke(args != null ? args : emptyArgs)這句代碼,loadServiceMethod()和invoke()是這個(gè)方法中關(guān)鍵作用的代碼;invoke()就是Retrofit創(chuàng)建Service實(shí)例的關(guān)鍵
abstract @Nullable T invoke(Object[] args);
點(diǎn)進(jìn)去發(fā)現(xiàn),這是ServiceMethod的抽象方法;那么只好看看loadServiceMethod方法的具體邏輯
ServiceMethod<?> loadServiceMethod(Method method) {
ServiceMethod<?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = ServiceMethod.parseAnnotations(this, method);
serviceMethodCache.put(method, result);
}
}
return result;
}
然后再點(diǎn)進(jìn)ServiceMethod.parseAnnotations()方法
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(method,"Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {
throw methodError(method, "Service methods cannot return void.");
}
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
在這個(gè)方法中主要看HttpServiceMethod.parseAnnotations(),這個(gè)方法的代碼就比較多了,我們主要看返回處的代碼
if (!isKotlinSuspendFunction) {
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
} else if (continuationWantsResponse) {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForResponse<>(requestFactory,callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
} else {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForBody<>(requestFactory,callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,continuationBodyNullable);
}
HttpServiceMethod是 ServiceMethod的子類,而HttpServiceMethod.parseAnnotations()是返回ServiceMethod對(duì)象,然后再執(zhí)行ServiceMethod的invoke方法,這里我們可以直接查看HttpServiceMethod的invoke方法
@Override final @Nullable ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
在invoke()中創(chuàng)建了一個(gè)OkHttpCall,然后調(diào)用了adapt()方法,返回我們需要的對(duì)象,那么我們就來(lái)看這個(gè)adapt()方法干了什么,繼續(xù)點(diǎn)進(jìn)去
protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);
又是一個(gè)抽象方法,看來(lái)直接查看adapt()方法行不通,那么就只好看看OkHttpCall做了什么了,我們點(diǎn)進(jìn)OkHttpCall看一下吧
final class OkHttpCall<T> implements Call<T> {
.......
}
OkHttpCall是繼承自Retrofit的Call的,也就是我們第一步?jīng)]走通的那個(gè)Call(因?yàn)镃all的enqueue方法是抽象的),那么它有沒(méi)有實(shí)現(xiàn)Call的enqueue()方法呢?
@Override public void enqueue(final Callback<T> callback) {
okhttp3.Call call;
synchronized (this) {
call = rawCall;
if (call == null && failure == null) {
call = rawCall = createRawCall();
}
}
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
Response<T> response = parseResponse(rawResponse);
callback.onResponse(OkHttpCall.this, response);
}
@Override public void onFailure(okhttp3.Call call, IOException e) {
callFailure(e);
}
});
}
由于enqueue()中代碼量較大,我精簡(jiǎn)了這部分代碼,enqueue()主要的工作是創(chuàng)建了一個(gè)okhttp3的Call,然后調(diào)用這個(gè)call的enqueue()方法去發(fā)起網(wǎng)絡(luò)請(qǐng)求,然后將回調(diào)結(jié)果預(yù)處理之后,交由Retrofit的Callback
因此,到這里我們對(duì)Retrofit的工作流程就有了一個(gè)大致的了解,Retrofit通過(guò)動(dòng)態(tài)代理創(chuàng)建出Service實(shí)例,然后通過(guò)這個(gè)實(shí)例調(diào)用對(duì)應(yīng)的api得到一個(gè)Retrofit的Call對(duì)象,這個(gè)Call對(duì)象又創(chuàng)建了一個(gè)OkHttp3的Call實(shí)例去發(fā)起網(wǎng)絡(luò)請(qǐng)求,然后將結(jié)果回調(diào)給Retrofit的Callback
在上面的分析過(guò)程中,有一個(gè)點(diǎn)還沒(méi)有解決,那就是我們?cè)趧?chuàng)建出OkHttpCall對(duì)象后,然后調(diào)用了adapt()方法,這個(gè)adapt()方法是干什么用的呢?做了哪些處理?
在工作中我們知道,adapter是適配器的意思,作為中間橋梁的作用;猜測(cè)是不是對(duì)OkHttpCall的轉(zhuǎn)換處理呢?因?yàn)槲覀冎繰etrofit可以和RxJava結(jié)合使用,是不是就是因?yàn)檫@個(gè)adapt()的作用呢?當(dāng)然,我們還需要查看源碼,才能找到答案
找到剛才那個(gè)抽象的adapt()方法,查看其實(shí)現(xiàn)的地方,我們會(huì)看到HttpServiceMethod內(nèi)部有一個(gè)靜態(tài)內(nèi)部類實(shí)現(xiàn)了該抽象方法
static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
private final CallAdapter<ResponseT, ReturnT> callAdapter;
CallAdapted(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,Converter<ResponseBody, ResponseT> responseConverter,CallAdapter<ResponseT, ReturnT> callAdapter) {
super(requestFactory, callFactory, responseConverter);
this.callAdapter = callAdapter;
}
@Override protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
return callAdapter.adapt(call);
}
}
在這個(gè)類中,創(chuàng)建了一個(gè)CallAdapter類,并將adapt()交由CallAdapter的adapt()來(lái)實(shí)現(xiàn),這時(shí)候我們可以聯(lián)想到在Retrofit初始化的時(shí)候,有這么一句代碼 addCallAdapterFactory(RxJava2CallAdapterFactory.create()),加上這句代碼后,我們就可以將Call對(duì)象轉(zhuǎn)化為Observable對(duì)象,和RxJava進(jìn)行交互了,看來(lái)這個(gè)adapt()方法很可能就是將OkHttpCall進(jìn)行轉(zhuǎn)換的作用,為了驗(yàn)證我們的猜想,繼續(xù)深入源碼分析
這個(gè)靜態(tài)內(nèi)部類的callAdapter是構(gòu)造方法傳進(jìn)來(lái)的,我們一步一步的向上找
CallAdapted -> callAdapter
HttpServiceMethod -> createCallAdapter()
Retrofit -> callAdapter()
Retrofit -> nextCallAdapter() callAdapterFactories.get()
最后我們發(fā)現(xiàn)CallAdapter來(lái)自callAdapterFactories變量,那么我們現(xiàn)在就需要找到callAdapterFactories的來(lái)源
// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
我們可以發(fā)現(xiàn)這個(gè)callAdapterFactories分了兩次添加,一次是callAdapterFactories變量,另一次是和平臺(tái)相關(guān)的默認(rèn)CallAdapterFactories,我們先看這個(gè)和平臺(tái)相關(guān)默認(rèn)的CallAdapterFactories,我們這里就只看Android平臺(tái)
@Override List<? extends CallAdapter.Factory> defaultCallAdapterFactories(@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
DefaultCallAdapterFactory executorFactory = newDefaultCallAdapterFactory(callbackExecutor);
return Build.VERSION.SDK_INT >= 24
? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
: singletonList(executorFactory);
}
首先聲明了一個(gè)Executor,看命名,這個(gè)Executor是用于回調(diào)的;然后創(chuàng)建了DefaultCallAdapterFactory(),我們點(diǎn)進(jìn)這個(gè)類,看它的get()方法做了什么操作
@Override public @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call<Object> adapt(Call<Object> call) {
return executor == null
? call
: new ExecutorCallbackCall<>(executor, call);
}
};
}
我只截取了核心代碼,我們可以看到在get()方法中返回了一個(gè)CallAdapter,還有一點(diǎn)應(yīng)該注意,我們找這個(gè)CallAdapter的原因是什么,是不是要弄清楚它的adapt()方法做了什么,剛開(kāi)始由于CallAdapter的adapt()是抽象方法,所以我們找到了現(xiàn)在這里;那么,現(xiàn)在我們可以看到DefaultCallAdapterFactory類的get()方法返回的是一個(gè)CallAdapter,在它的adapt()方法里返回了ExecutorCallbackCall對(duì)象,還記得OkHttpCall么?當(dāng)時(shí)OkHttpCall是通過(guò)adapt(call)方法傳進(jìn)來(lái)的,DefaultCallAdapterFactory類里又原封不動(dòng)的傳給了ExecutorCallbackCall類,現(xiàn)在ExecutorCallbackCall對(duì)象做了什么處理
static final class ExecutorCallbackCall<T> implements Call<T> {
final Executor callbackExecutor;
final Call<T> delegate;
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
@Override public void enqueue(final Callback<T> callback) {
delegate.enqueue(new Callback<T>() {
@Override public void onResponse(Call<T> call, final Response<T> response) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
if (delegate.isCanceled()) {
// Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
} else {
callback.onResponse(ExecutorCallbackCall.this, response);
}
}
});
}
@Override public void onFailure(Call<T> call, final Throwable t) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
callback.onFailure(ExecutorCallbackCall.this, t);
}
});
}
});
}
}
可以看到,ExecutorCallbackCall是DefaultCallAdapterFactory的靜態(tài)內(nèi)部類,繼承自Retrofit的Call,與OkHttpCall是同類的,它的作用是把操作切回主線程后再交給Callback
分析完這個(gè)和平臺(tái)相關(guān)的默認(rèn)CallAdapter,我們?cè)賮?lái)看看callAdapterFactories變量中的CallAdapter,我們點(diǎn)擊callAdapterFactories變量,看看哪里對(duì)它進(jìn)行了添加操作
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
callAdapterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
fun instance(): Retrofit =
Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.baseUrl("https://api.github.com/")
.build()
這些就明白了,這個(gè)CallAdapter是我們初始化Retrofit時(shí)我們主動(dòng)添加進(jìn)去的,我們這里添加的CallAdapterFactory是和RxJava結(jié)合使用的,像下面這樣
//GithubService.kt
@GET("/users/{user}/repos")
fun listRepos(@Path("user") user: String): Observable<List<Repo>>
//發(fā)起網(wǎng)絡(luò)請(qǐng)求
val repoService = Net.instance().create(GithubService::class.java)
repoService.listRepos("hsicen")
.observeOn(Schedulers.newThread())
.subscribe(object : Observer<List<Repo>> {
override fun onComplete() {
}
override fun onSubscribe(d: Disposable?) {
}
override fun onNext(value: List<Repo>?) {
}
override fun onError(e: Throwable?) {
}
})
但是Observable回調(diào)的接口太多了,在App中更推薦使用Single
//GithubService.kt
@GET("/users/{user}/repos")
fun listRepos(@Path("user") user: String): Observable<List<Repo>>
//發(fā)起網(wǎng)絡(luò)請(qǐng)求
val repoService = Net.instance().create(GithubService::class.java)
repoService.listRepos("hsicen")
.observeOn(Schedulers.newThread())
.subscribe(object : SingleObserver<List<Repo>> {
override fun onSubscribe(d: Disposable?) {
}
override fun onSuccess(value: List<Repo>?) {
}
override fun onError(e: Throwable?) {
}
})
源碼分析總結(jié)
通過(guò) Retrofit.create(Class) ?法創(chuàng)建出 Service interface 的實(shí)例,從?使得 Service 中配置的方法變得可用,這是 Retrofit 代碼結(jié)構(gòu)的核心
Retrofit.create() ?法內(nèi)部,使?的是Proxy.newProxyInstance() ?法來(lái)創(chuàng)建Service實(shí)例。這個(gè)方法會(huì)為參數(shù)中的多 interface(具體到Retrofit來(lái)說(shuō),是固定傳入?個(gè)interface)創(chuàng)建一個(gè)對(duì)象,這個(gè)對(duì)象實(shí)現(xiàn)了所有interface的每個(gè)方法,并且每個(gè)方法的實(shí)現(xiàn)都是雷同的:調(diào)?對(duì)象實(shí)例內(nèi)部的一個(gè)InvocationHandler 成員變量的 invoke() ?法,并把??的?法信息傳遞進(jìn)去。這樣就在實(shí)質(zhì)上實(shí)現(xiàn)了代理邏輯:interface 中的?法全部由?個(gè)另外設(shè)定的InvocationHandler對(duì)象來(lái)進(jìn)?代理操作。并且,這些?法的具體實(shí)現(xiàn)是在運(yùn)行時(shí)? interface實(shí)例時(shí)才確定的,?不是在編譯時(shí)(雖然在編譯時(shí)就已經(jīng)可以通過(guò)代碼邏輯推斷出來(lái))。這就是「動(dòng)態(tài)代理理機(jī)制」的具體含義。
-
因此,invoke() ?法中的邏輯,就是 Retrofit 創(chuàng)建 Service 實(shí)例的關(guān)鍵。這個(gè)?法內(nèi)有三行關(guān)鍵代碼,共同組成了具體邏輯:
ServiceMethod 的創(chuàng)建
loadServiceMethod(method)
這?代碼負(fù)責(zé)讀取 interface 中原方法的信息(包括返回值類型、?法注解、參數(shù)類型、參數(shù)注解),并將這些信息做初步分析。實(shí)際返回的是一個(gè) HttpServiceMethodOkHttpCall 的創(chuàng)建
new OkHttpCall<>(requestFactory, args, callFactory, responseConverter)
OkHttpCall是retrofit2.Call 的子類。這行代碼負(fù)責(zé)將ServiceMethod解讀到的信息(主要是一個(gè) RequestFactory 、一個(gè) OkHttpClient 和?個(gè) ResponseConverter )封裝進(jìn) OkHttpCall ;而這個(gè)對(duì)象可以在需要的時(shí)候(例如它的 enqueue() ?法被調(diào)?的時(shí)候),利用RequestFactory和OkHttpClient來(lái)創(chuàng)建一個(gè)okhttp3.Call對(duì)象,并調(diào)?這個(gè)okhttp3.Call對(duì)象來(lái)進(jìn)行?絡(luò)請(qǐng)求的發(fā)起,然后利用ResponseConverter對(duì)結(jié)果進(jìn)行預(yù)處理之后,交回給 Retrofit 的 Callbackadapt()?法
return callAdapter.adapt(new OkHttpCall...)
這個(gè)方法會(huì)使用一個(gè)CallAdapter對(duì)象來(lái)把OkHttpCall對(duì)象進(jìn)行轉(zhuǎn)換,?成?個(gè)新的對(duì)象。默認(rèn)情況下,返回的是?個(gè)ExecutorCallbackCall,它的作用是把操作切回主線程后再交給Callback 。另外,如果有自定義的CallAdapter,這里也可以?成別的類型的對(duì)象,例例如 RxJava 的Observable ,來(lái)讓 Retrofit 可以和 RxJava 結(jié)合使用。
Retrofit使用總結(jié)
1. 如果要直接獲取網(wǎng)絡(luò)返回的字符串,使用ResponseBody作為參數(shù)
@GET("sore")
Call<ResponseBody> getLol();
2. 一個(gè)Call只能被執(zhí)行一次,如果要多次執(zhí)行Call對(duì)象,可以通過(guò)clone,來(lái)clone一份call,從新調(diào)用
Call newCall = mCall.clone()
3. 固定參數(shù)查詢,不需要?jiǎng)討B(tài)添加參數(shù),直接調(diào)用查詢
@GET("/some/endpoint?fixed=query")
Call<User> someEndpoint();
apiService.someEndpoint();
GET /some/endpoint?fixed=query HTTP/1.1
4. 動(dòng)態(tài)參數(shù)查詢,每次網(wǎng)絡(luò)請(qǐng)求查詢指定參數(shù)的內(nèi)容
@GET("/some/endpoint")
Call<User> someEndpoint( @Query("dynamic") String dynamic);
apiService.someEndpoint("query");
GET /some/endpoint?dynamic=query HTTP/1.1
5. 動(dòng)態(tài)Map參數(shù)查詢
@GET("/some/endpoint")
Call<User> someEndpoint(@QueryMap Map<String, String> dynamic);
apiService.someEndpoint(Collections.singletonMap("dynamic", "query"));
GET /some/endpoint?dynamic=query HTTP/1.1
6. 省略動(dòng)態(tài)參數(shù)查詢
@GET("/some/endpoint")
Call<User> someEndpoint(@Query("dynamic") String dynamic);
apiService.someEndpoint(null);
GET /some/endpoint HTTP/1.1
7. 固定+動(dòng)態(tài)參數(shù)查詢
@GET("/some/endpoint?fixed=query")
Call<User> someEndpoint(@Query("dynamic") String dynamic);
apiService.someEndpoint("query");
GET /some/endpoint?fixed=query&dynamic=query HTTP/1.1
8. 路徑替換查詢
@GET("/some/endpoint/{thing}")
Call<User> someEndpoint( @Path("thing") String thing);
apiService.someEndpoint("bar");
GET /some/endpoint/bar HTTP/1.1
8. 固定頭查詢
@GET("/some/endpoint")
@Headers("Accept-Encoding: application/json")
Call<User> someEndpoint();
apiService.someEndpoint();
GET /some/endpoint HTTP/1.1
Accept-Encoding: application/json
9. 動(dòng)態(tài)頭查詢
@GET("/some/endpoint")
Call<User> someEndpoint(@Header("Location") String location);
apiService.someEndpoint("Droidcon NYC 2015");
GET /some/endpoint HTTP/1.1
Location: Droidcon NYC 2015
10. 固定+動(dòng)態(tài)頭查詢
@GET("/some/endpoint")
@Headers("Accept-Encoding: application/json")
Call<User> someEndpoint(@Header("Location") String location);
apiService.someEndpoint("Droidcon NYC 2015");
GET /some/endpoint HTTP/1.1
Accept-Encoding: application/json
Location: Droidcon NYC 2015
11. Post請(qǐng)求,無(wú)Body
@POST("/some/endpoint")
Call<SomeResponse> someEndpoint();
apiService.someEndpoint();
POST /some/endpoint HTTP/1.1
Content-Length: 0
12. Post請(qǐng)求有Body
@POST("/some/endpoint")
Call<SomeResponse> someEndpoint(@Body SomeRequest body);
apiService.someEndpoint();
POST /some/endpoint HTTP/1.1
Content-Length: 3
Content-Type: text/html
xdadasd
13. 表單編碼字段
@FormUrlEncoded
@POST("/some/endpoint")
Call<User> someEndpoint( @Field("name1") String name1, @Field("name2") String name2);
apiService.someEndpoint("value1", "value2");
POST /some/endpoint HTTP/1.1
Content-Length: 25
Content-Type: application/x-www-form-urlencoded
name1=value1&name2=value2
14. 表單編碼字段(Map)
@FormUrlEncoded
@POST("/some/endpoint")
Call<User> someEndpoint( @FieldMap Map<String, String> names);
apiService.someEndpoint(ImmutableMap.of("name1", "value1", "name2", "value2"));
POST /some/endpoint HTTP/1.1
Content-Length: 25
Content-Type: application/x-www-form-urlencoded
name1=value1&name2=value2
15. 動(dòng)態(tài)Url(Dynamic URL parameter)
@GET
Call<List<Activity>> getActivityList(@Url String url,@QueryMap Map<String, String> map);
Call<List<Activity>> call = service.getActivityList("http://115.159.198.162:3001/api/ActivitySubjects", map);