原文地址
Retrofit — Synchronous and Asynchronous Requests
同步請求
在Retrofit1.9中盒揉,同步請求通過聲明一個返回類型,下面的例子展示了在執(zhí)行 getTasks
方法時會返回一個task類型的列表
Retrofit 1.9
public interface TaskService {
@GET("/tasks")
List<Task> getTasks();
}
Retrofit 2
public interface TaskService {
@GET("/tasks")
Call<List<Task>> getTasks();
}
在Retrofit 2中,每個請求被包裝成一個 Call
對象藕漱,實際上同步和異步請求在執(zhí)行請求方法后創(chuàng)建了一個Call類型的對象肋联。在Retrofit2中橄仍,同步和異步請求的接口定義是一樣的牍戚。同步方法被執(zhí)行在主線程侮繁,這意味著UI線程將會被阻塞在請求執(zhí)行的時間段內(nèi)。
Warning: 同步請求可能是導(dǎo)致APP在4.0及以上版本崩潰的原因如孝,你可能會得到一個
NetworkOnMainThreadException
的異常錯誤
同步方法提供了直接實時返回值的能力宪哩,因為這個操作在進行網(wǎng)絡(luò)請求時會阻塞一切,為了不阻塞UI第晰,你不得不將這個操作放在其他的線程中并將請求結(jié)果handle出來锁孟,這樣就能在等待返回期間繼續(xù)操作主線程。
從同步請求中取數(shù)據(jù)
讓我們先回到請求上茁瘦,同步請求在Retrofit從v1版本到v2版本已經(jīng)有了改變品抽,下面的代碼示例展示了用Retrofit進行同步請求, ServiceGenerator
這個在前面的文章中已經(jīng)有說明甜熔。
Retrofit 1.9
TaskService taskService = ServiceGenerator.createService(TaskService.class);
List<Task> tasks = taskService.getTasks();
Retrofit 2
TaskService taskService = ServiceGenerator.createService(TaskService.class);
Call<List<Task>> call = taskService.getTasks();
List<Task>> tasks = call.execute().body();
在Retrofit 2中調(diào)用這個call對象的 execute()
方法會產(chǎn)生同步請求圆恤,返回的對象通過 body()
方法獲取反序列化出來的數(shù)據(jù)。
異步請求
相對于同步請求,Retrofit也同時支持異步請求,Retrofit 1.9中異步請求是沒有返回值的拆火,定義的方法需要一個 callback
作為最后一個參數(shù)。
Retrofit 1.9
public interface TaskService {
@GET("/tasks")
void getTasks(Callback<List<Task>> cb);
}
Retrofit 2
public interface TaskService {
@GET("/tasks")
Call<List<Task>> getTasks();
}
Retrofit在一個另外的線程中執(zhí)行這個方法,這個 Callback
是一個通用的類并且會匹配你定義的返回類型。我們的例子返回了一個tasks的list,在Callback內(nèi)部自己做了映射赐稽。
前面已經(jīng)提到在Retrofit 2中同步請求和異步請求定義的接口是一樣的蠢莺,目標返回類型被封裝成一個 Call
對象考蕾,實際的請求類型在泛型中。
從異步請求中取數(shù)據(jù)
使用異步請求會讓你強制實現(xiàn) Callback
的兩個方法 success
和 failure
,你可以在對應(yīng)的回調(diào)方法中實現(xiàn)你想在請求結(jié)束做的事情荷鼠,下面的代碼示例展示了一個實現(xiàn)的例子牍疏。
Retrofit 1.9
TaskService taskService = ServiceGenerator.createService(TaskService.class);
taskService.getTasks(new Callback<List<Task>>() {
@Override
public void success(List<Task> tasks, Response response) {
// here you do stuff with returned tasks
}
@Override
public void failure(RetrofitError error) {
// you should handle errors, too
}
});
Retrofit 2
TaskService taskService = ServiceGenerator.createService(TaskService.class);
Call<List<Task>> call = taskService.getTasks();
call.enqueue(new Callback<List<Task>>() {
@Override
public void onResponse(Call<List<Task>> call, Response<List<Task>> response) {
if (response.isSuccessful()) {
// tasks available
} else {
// error response, no access to resource?
}
}
@Override
public void onFailure(Call<List<Task>> call, Throwable t) {
// something went completely south (like no internet connection)
Log.d("Error", t.getMessage());
}
}
得到原始的HTTP請求返回數(shù)據(jù)
有時候我們需要拿到原始的HTTP返回的數(shù)據(jù)而不是經(jīng)過映射后的數(shù)據(jù)编矾,只需要將 Response
定義成函數(shù)的返回碘菜,這個類的使用方法和其他的類一樣。
Retrofit 1.9
// synchronous
@GET("/tasks")
Response getTasks();
// asynchronous
@GET("/tasks")
void getTasks(Callback<Response> cb);
Retrofit 2
接收原始返回數(shù)據(jù)的方式從Retrofit v1到v2版本定義上是一樣的(無論是同步還是異步)凿滤,也就是說鼻种,你不需要額外定義一個 Response
類做為一個返回類型,但是你可以拿到返回值在 onResponse()
的回調(diào)中,下面就是代碼的示例展示如何獲取原始的數(shù)據(jù)雁芙。
call.enqueue(new Callback<List<Task>>() {
@Override
public void onResponse(Call<List<Task>> call, Response<List<Task>> response) {
// get raw response
Response raw = response.raw();
}
@Override
public void onFailure(Call<List<Task>> call, Throwable t) {}
}
Additional Resources
Retrofit API declaration, section synchronous vs. asynchronous vs. observable