開新坑辣!一直覺得自己框架了解的特別少,大多隻知其名而不知實現原理,然而幾乎每次面試都會被問及框架。所以很有必要總結一些常用的框架,希望自己能堅持把這個『框架學習』系列的新坑填的厚實一點!
先從網路框架中大名鼎鼎的Retrofit開始吧,本篇先對Retrofit有個瞭解,目錄如下:
- 概述
- 使用方式
1.概述
a.Retrofit是Square公司推出的一個基於RESTful風格的HTTP網路框架。
相關連結地址:
b.與OkHttp的關係:
是對OkHttp網路請求框架的二次封裝,本質仍是OkHttp。即網路請求的工作本質上是由OkHttp完成,而Retrofit僅負責網路請求介面的封裝。流程如圖:
- App應用程式通過Retrofit請求網路,實際上是使用Retrofit介面層封裝請求引數、Header、Url等資訊,之後由OkHttp完成後續的請求操作。
- 在服務端返回資料之後,OkHttp將原始的結果交給Retrofit,Retrofit會根據使用者的需求對結果進行解析。
- 通過使用大量的設計模式進行功能模組的解耦,使得上面的過程進行得更加簡單和流暢。
c.其他網路框架簡介:
- AndroidAsynHttp:基於HttpClient,已經停止維護,Android5.0不再使用HttpClient。
- Volley:基於HttpUrlConnection,由谷歌官方推出,適合輕量級網路互動,如資料傳輸量小的場景,而不適合大檔案傳輸。
相比於上述兩種網路框架,Retrofit具有的優點:
- 遵循Restful API設計風格,簡潔易用
- 支援同步&非同步網路請求
- 支援多種資料的解析&序列化格式(Gson、 Json、XML、 Protobuf)
- 支援對RxJava支援
- 註解化配置高度解耦、採用大量設計模式簡化使用
2.使用方式
大致分成八個步驟:
step1:新增Retrofit庫、OkHttp庫、資料解析器整合庫的依賴,並註冊網路許可權
在app檔案包下的build.gradle中新增依賴,這裡用的是JSON資料解析器:
compile 'com.squareup.retrofit2:retrofit:2.4.0'
compile 'com.squareup.okhttp3:okhttp:3.10.0'
compile 'com.squareup.retrofit2:converter-gson:2.4.0'
複製程式碼
在AndroidManifest.xml中註冊許可權:
<uses-permission android:name="android.permission.INTERNET"/>
複製程式碼
step2:建立接收伺服器返回資料的類
請求後伺服器會返回資料,需要根據返回資料的格式和解析方式(Json、XML等)來定義實體類Model。
假設有返回資料格式為如下JSON,其中,如果使用者名稱和密碼匹配成功,則code值為1,反之為0:
{
"code":1,
"data":{
"id":10001,
"username":"Tom",
"email":"888888888@qq.com",
"tel":"18088888888"
},
"message":"success"
}
複製程式碼
則對應的實體類UserInfoModel:
public class UserInfoModel {
public int code;
public UserInfo data;
public String message;
public static class UserInfo{
public int id;
public String username;
public String email;
public String tel;
}
}
複製程式碼
step3:建立用於描述網路請求的介面
定義一個網路請求的介面,介面函式裡要定義URL路徑、請求引數、返回型別。其中,需要使用註解來描述請求型別和請求引數。
public interface Interface {
@GET("URL")
Call<Model> getCall(@Query("xxx") String xxx);
// 用@GET("URL")宣告瞭URL路徑
// 用getCall()接收網路請求資料,並用註解@Query("xxx") 宣告瞭請求引數
// 該方法會返回一個Retrofit的Call物件,這裡宣告瞭這個物件處理的資料型別為自定義Model
}
複製程式碼
在上例中,對應的UserMgrService介面如下,當傳送請求引數為Tom和123456時,請求將傳送給的URL為『login?username=Tom&pwd=123456』,並會返回之前定義的GSON資料:
public interface UserMgrService{
@GET("login")
Call<UserInfoModel> login(@Query("username") String username,@Query("pwd") String pwd);
}
複製程式碼
常用的註解含義如圖:
這裡可以發現,@GET和@Query搭配使用,@POST和@Field搭配使用。
step4:建立Retrofit物件並設定資料解析器
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("URL") //設定網路請求的Url地址,注意以要以斜線(代表根目錄)結尾
.addConverterFactory(GsonConverterFactory.create()) //設定資料解析器,這裡表示用的是JSON解析返回值
.build();
複製程式碼
常用的資料解析器如圖:
step5:生成介面物件
由於是interface不是class,無法直接呼叫內部方法,需要利用已建立的Retrofit物件去生成代理的介面物件。
UserMgrService service=retrofit.create(UserMgrService.class);
複製程式碼
step6:呼叫介面方法返回Call物件
呼叫介面物件的方法,返回一個可以執行網路訪問的網路工作物件。
Call<UserInfoModel> call=service.login("Tom","123456");
複製程式碼
step7:傳送網路請求(非同步 / 同步)
a.同步:呼叫Call物件execute()
,返回結果是響應體。
//開執行緒進行網路請求
new Thread(new Runable()){
@Override
pubblic void run(){
Response<UserInfoModel> response=null;
try{
response=call.execute();
}catch{
e.printStackTrace();
}
//處理伺服器返回的資料
}
}.start();
複製程式碼
b.非同步:呼叫Call物件enqueue()
,引數是一個回撥。
//非同步時,框架中已經封裝好資料轉換、執行緒切換的操作,無需手動開執行緒
call.enqueue(new CallBack<UserInfoModel>(){
@Override
public void onResponse(Call<UserInfoModel> call,Response<UserInfoModel> response){
//處理伺服器返回的資料
}
@Override
public void onFailure(Call<UserInfoModel> call,Throwable t){
}
});
複製程式碼
step8: 處理伺服器返回的資料
現在可以去列印出返回結果:
Log.i("response","code:"+response.body().code);//結果為"code:1"
複製程式碼
下面給出官方給的simple demo,便於更好的理解Retrofit的使用步驟:
//step3:
public interface GitHub {
@GET("/repos/{owner}/{repo}/contributors")
Call<List<Contributor>> contributors(
@Path("owner") String owner,
@Path("repo") String repo);
}
public static void main(String... args) throws IOException {
// step4:Create a very simple REST adapter which points the GitHub API.
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
// step5:Create an instance of our GitHub API interface.
GitHub github = retrofit.create(GitHub.class);
// step6:Create a call instance for looking up Retrofit contributors.
Call<List<Contributor>> call = github.contributors("square", "retrofit");
// step7:Fetch and print a list of the contributors to the library.
List<Contributor> contributors = call.execute().body();
//step8:
for (Contributor contributor : contributors) {
System.out.println(contributor.login + " (" + contributor.contributions + ")");
}
}
複製程式碼
例項:這是一份很詳細的 Retrofit 2.0 使用教程(含例項講解)
以上,可以看到,Retrofit可根據不同的介面定義,靈活地生成對應的網路工作物件,然後利用這個物件去訪問網路。它就像一個工廠,只提供產品,本身不處理網路請求,而是讓產品去處理網路請求。
下一篇將進行Retrofit的原始碼分析~