Retrofit
不是網絡請求框架,而是對網絡請求框架的封裝,是整個框架的門面類,整個入口,可以通過這個方法進行我們的請求的配置,配置的方式就是通過里面的一個內部類Builder,使用構建者模式創建,里面有個重要的變量就是ServiceMethod
ServiceMethod
對應我們寫好的接口類中的方法,通過動態代理的模式,通過這個可以將我們定義好的方法(包含方法里面的參數,注解)轉換成一個一個的http請求。同時ServiceMethod可以幫我們解析方法中的注解,生成我們需要的Request對象。在ServiceMethod這個類中生成了三個重要的工廠類CallAdapter工廠、Converter工廠
- CallAdapter工廠
默認把網絡請求封裝成okhttpcall,這個作用就是將okhttpcall轉換成適合不同平臺使用的解析(比如java8,ios,android平臺) - Converter工廠
是用于生產數據轉換,默認情況下是把okhttp返回的response對象轉換成我們的java對象進行使用。而在Retrofit里面默認是使用Gson來解析數據 - CallFactory工廠
用于創建Call請求類,http請求會抽象封裝成call類,同時表示請求已經準備好了,隨時可以運行
這個時候通過這幾個工廠類的創建和配合,可以創建出OkHttpCall請求,可以進行同步或者異步請求,可以看出,Retrofit只是對okhttpcall的一層封裝,底層還是通過okhttp進行的網絡請求。
當通過okhttpcall進行請求,對之前ServiceMethod生成的一些地址,參數,請求之后(同步或者異步都行),返回結果之后,就會通過之前創建好的CallAdapter工廠,把okhttpcall轉換成不同平臺使用的。
然后通過Converter進行數據轉換,最終得到一個response對象,然后最后通過callbackExecutor進行線程切換(子線程請求數據,主線程更新UI),當然了這個只是針對異步請求,同步請求是不需要這個的。
簡單的使用
請求流程
首先確定的一點就是,Retrofit是一個網絡請求框架的封裝工具類,而不是一個網絡請求框架,他底層使用的是okhttp這個網絡請求框架,只是在okhttp的基礎上進行了更深層次的封裝,更加簡單易用。所以流程就是
App->Retrofit: 發送請求
Retrofit-->App: 數據(解析好)
Retrofit->OkHttp: 我要請求數據
OkHttp-->Retrofit: 請求好數據返回
OkHttp->Server: 后臺,給我數據
Server-->OkHttp: 吶,數據給你
- App應用程序通過Retrofit請求網絡,實際上是使用Retrofit接口層封裝請求參數和HTTP方式,之后交由OkHttp完成后續的網絡請求工作
- 在服務端返回數據之后,OkHttp將原始的結果交給Retrofit,Retrofit根據用戶的需求對數據進行解析,然后進行相關邏輯操作
代碼演示
例子一
- Retrofit turns your HTTP API into a Java interface.
public interface GitHubService {
// @GET 表示get請求方法
// users/{user}/repos 這個就是和baseurl進行拼接 是個完整的請求地址
//{user} 這個大括號,表示里面的參數是動態的可以更換的 具體的值就是對應@Path("user") String user 這個傳遞進入的user
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
- The Retrofit class generates an implementation of the GitHubService interface.
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
GitHubService service = retrofit.create(GitHubService.class);
- Each Call from the created GitHubService can make a synchronous or asynchronous HTTP request to the remote webserver.
Call<List<Repo>> repos = service.listRepos("octocat");
repos.enqueue(new Callback(){
@Override
public void onFailure(Call call,IOException e){
//請求出錯進行的邏輯
}
@Override
public void onResponse(Call call ,Response response) throws IOException{
//在這里進行的是成功數據只會的相關請求
}
})
例子二
1、添加網絡權限
<uses-permission android:name="android.permission.INTERNET"/>
2、創建一個接受的返回類型
class HttpResult<T> {
private int count;
private int err;
private int total;
private int page;
private int refresh;
//用來模仿Data
private T items;
}
class TestBean{
private String format;
private long published_at;
private String content;
private String state;
}
public class User {
/**
* avatar_updated_at : 1418571809
* uid : 13846208
* last_visited_at : 1390853782
* created_at : 1390853782
* state : active
* last_device : android_2.6.4
* role : n
* login : ---切隨緣
* id : 13846208
* icon : 20141215074328.jpg
*/
private int avatar_updated_at;
private int uid;
private int last_visited_at;
private int created_at;
private String state;
private String last_device;
private String role;
private String login;
private int id;
private String icon;
}
3、創建服務接口
public interface TestInterface {
//每個方法參數都需要進行注解標志 要不然就會報錯 這個在后面的分析詳細邏輯的時候會講
@GET("article/list/latest?page=1")
Call<HttpResult<List<TestBean>>> getQiuShiJsonString();
}
4、創建Retrofit實例
public static Retrofit getRetrofit() {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.connectTimeout(10, TimeUnit.SECONDS);
return new Retrofit.Builder()
.client(builder.build())
//設置請求網絡地址的url(基地址 這個地址一定要"/"結尾 要不會出現問題)
// public Builder baseUrl(HttpUrl baseUrl) {
//checkNotNull(baseUrl, "baseUrl == null");
//List<String> pathSegments = baseUrl.pathSegments();
// if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
// throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
// }
// this.baseUrl = baseUrl;
// return this;
//}
.baseUrl("http://m2.qiushibaike.com/")
.addConverterFactory(GsonConverterFactory.create()) //設置數據解析器 默認使用的Gson
.addCallAdapterFactory(RxJavaCallAdapterFactory.create()) //設置支持RxJava轉換器
.build();
}
5、創建網絡請求的接口實例
TestInterface service = getRetrofit().create(TestInterface.class);
6、通過接口實例創建call方法
Call<HttpResult<List<TestBean>>> qiuShiJson = service.getQiuShiJsonString();
7、通過call執行異步(或者同步方法)
qiuShiJson.enqueue(new Callback<HttpResult<List<TestBean>>>() {
@Override
public void onResponse(Call<HttpResult<List<TestBean>>> call, Response<HttpResult<List<TestBean>>> response) {
Log.d("TestRetrofit", "請求回來的數據");
if (response.isSuccessful()){
HttpResult<List<TestBean>> body = response.body();
Log.d("TestRetrofit", "body.getSubjects().size():" + body.getSubjects().size());
}
}
@Override
public void onFailure(Call<HttpResult<List<TestBean>>> call, Throwable t) {
Log.d("TestRetrofit", "請求數據失敗,失敗的原因" + t.getMessage());
}
});