Retrofit原始碼解讀(一)--Retrofit簡單流程
標籤(空格分隔):Retrofit原始碼 學習筆記
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());
}
});
複製程式碼
專案地址
開源專案Retrofit原始碼檢視和總結
開源專案Retrofit原始碼檢視和總結
開源專案Retrofit原始碼檢視和總結