Retrofit是Square公司開發的一個類型安全的Java和Android 的REST客戶端庫,這個庫爲網絡認證、API請求以及用OkHttp發送網絡請求提供了強大的框架 。Retrofit 庫使得從web api下載JSON 或者xml數據變的很是簡單直接,一旦數據下載完成即將其解析成普通java類(POJO)。
Retrofit支持Java 7 或 Android 2.3及以上版本。java
注:Rest API是一種軟件設計風格,服務器做爲資源存放地。客戶端去請求GET,PUT, POST,DELETE資源。而且是無狀態的,沒有session的參與。git
Retrofit使用的最核心的兩個技術:動態代理和Java反射。Retrofit很是巧妙的用註解來描述一個HTTP請求,將一個HTTP請求抽象成一個Java接口,而後用了Java動態代理的方式,動態的將這個接口的註解「翻譯」成一個HTTP請求,最後再執行這個HTTP請求。github
Retrofit無非就是讓用戶建立接口,並在接口中指定網絡訪問路徑、規則,把接口傳入Retrofit,Retrofit進行層層解析,而後調用OkHttp完成實際的網絡請求並將請求結果處理後返回給用戶。web
底層使用OkHttp進行網絡傳輸,性能好,速度快;json
擁有出色的API文檔和社區支持api
能夠自動將REST API返回的數據轉化爲Java對象,且支持多種數據轉換格式(如json、xml等)瀏覽器
使用Java註解聲明HTTP請求安全
支持 Multipart請求和文件上傳服務器
下面經過一個實際的例子介紹Retrofit的使用流程。該示例程序經過使用Retrofit向https://api.github.com/ 獲取指定github用戶的相關信息。目前Retrofit的最新版本爲2.0版,與此前的1.9有比較大的不一樣,該示例代碼是基於Retrofit2.0實現的。網絡
注:在瀏覽器輸入網址https://api.github.com/users/"想要查詢的github用戶名",服務器便會返回一個包含該用戶信息的json字符串,如輸入https://api.github.com/users/littleshuang ,所獲得的json字符串爲
第一步:添加依賴(gradle)
//retrofit底層網絡框架爲OkHttp,因此必須添加OkHttp的依賴包 compile 'com.squareup.okhttp3:okhttp:3.2.0' //retrofit的依賴包 compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4' //添加了一個官方提供的json conventer compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'
第二步:構建返回數據對應的實體類
注:Retrofit能夠自動根據咱們提供的conventer將返回數據轉化爲JOPO,因此咱們須要建立一個返回數據的實體類
本實例中根據前述json數據格式建立了一個User類
第三步:定義一個請求數據的接口,該接口中包含用於請求數據的方法定義(此例中定義了一個名爲ServiceInterface的接口,其中包含一個獲取用戶信息的get請求)
@GET:retrofit提供的一個用於定義請求方法的註解,retrofit會根據該註解將該方法解析爲一個相應請求類型的http請求
users/{user}:http請求的相對路徑,該路徑爲相對於自定義的BaseURL的路徑,該示例中的BaseURL爲:https://api.github.com/ ;大括號包裹的{user}是retrofit提供的一種動態生成URL地址的方式,大括號中包含的內容的具體類型和數據須要經過註解@Path後面的參數得到,此例中爲一個String類型變量,具體值由user變量提供
注:此處也可使用絕對路徑,但通常來講,同一項目中的絕大部分網絡請求都是基於同一服務器基址,變化的只是後面的相對路徑,因此推薦使用BaseURL + 相對路徑的方式,這種方式既能減小沒必要要的冗餘代碼,使代碼更加簡潔,又能減小出錯機率、提升重構效率。
Call<T>:retrofit中定義的一個接口,該接口中主要定義了同步請求(execute)、異步請求(enqueue)、取消請求(cancle)等方法,該接口的實現類經過實現這些方法執行具體的網絡請求操做;雖然Retrofit默認使用OkHttp執行具體的網絡請求操做,可是,咱們能夠經過本身實現該接口而採用本身的邏輯來執行網絡請求,這種方式很是插件化,從而很是靈活
第四步:使用Retrofit對象執行網絡請求
// 獲取一個Retrofit對象,並設置該對象的BaseURL和conventer Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com/") .addConverterFactory(GsonConverterFactory.create()) .build(); // service其實是create方法返回的一個ServiceInterface接口的動態代理 ServiceInterface service = retrofit.create(ServiceInterface.class); // 經過下面這個語句就建立了一個向獲取數據的get請求 Call<User> call = service.getUser("littleshuang"); // enqueue是一個異步請求方法 call.enqueue(new Callback<User>() { @Override public void onResponse(Call<User> call, Response<User> response) { if (response.isSuccess()){ // isSuccess()函數的處理邏輯很是簡單,只是判斷了下response的返回碼是否爲200,是即true,不然false // 因此能夠本身根據本身的須要進行處理 User user = response.body(); if (user != null){ etRetrofitGetUser.setText("User login: " + user.getLogin()); } } } @Override public void onFailure(Call<User> call, Throwable t) { etRetrofitGetUser.setText("Sth wrong!"); } });
結果展現:左右兩圖分別展現的是網絡請求成功和失敗兩種狀況下的結果
Retrofit源碼下面的http包中包含了Retrofit中定義的所有22中註解類型,這些註解都是用於控制HTTP請求的一些接口方法,下面對這些註解進行簡單的介紹,便於之後的使用
請求方法類:@GET @HEAD @POST @DELETE @PUT @OPTIONS @PATCH,這幾個註解分別表示定義一個get、head、post、delete、put、options或patch請求;
HTTP請求體:@BODY,該註解適用於在使用post或put請求時想要直接控制HTTP請求體的狀況,此註解參數不能爲空;
定義一個表單形式的請求:@FormUrlEncoded及@Field(或@FieldMap),該註解適用於須要使用表單形式提交一個名值對的表單數據的情形,@FormUrlEncoded聲明該請求的請求體爲表單形式,@Field定義請求體中的一組名值對,而@FieldMap定義多個名值對的組合
For example:
@FormUrlEncoded @POST("users/{user}") User updateUser(@Field("id") int id, @Field("name") String name); @FormUrlEncoded @POST("users/") Call<User> add(@FieldMap Map<String, String> fields);
使用 service.updateUser(1, "Bob")時,請求體爲id=1&name=Bob
使用service.add("name", "Bob", "nickname", "LittleBob")時,請求體爲name=Bob&nickname=LittleBob
HTTP請求頭:@HEADER 和@HEADERS,注意這二者的區別,二者都可以用於定義請求頭部信息,可是前者會覆蓋以前定義的頭部信息,然後者不會,只會在後面進行追加;因此當屢次對同一名稱的頭域進行賦值時,使用前者只會保留最後一次的賦值,即一個頭域至多隻有一個賦值,而使用後者則會保留全部的賦值,即一個頭域對應多個取值;
自定義HTTP請求客戶端:@HTTP
定義一個Multi-part類型的請求:@Multipart和@Part(或@PartMap),該註解適用於請求體爲Multi-part類型的請求,@Multipart聲明一個Multi-part類型的請求,@Part定義一個Multi-part類型請求的一個單一部分,@PartMap定義一個一個Multi-part類型請求的名值對,用法相似於表單形式的請求的用法,就不詳細介紹了
@Path:該註解後面的參數用於替換url中{}包含的部份內容
查詢參數:@Query和@QueryMap分別定義一個查詢參數和一個查詢參數鍵值對
@Streaming:定義該註解表示將請求方法的返回值直接以流的形式返回,而不解析爲Java實體類
@Url:該Url是一個相對於BaseURL的一個路徑,定義該參數就表示該請求方法的相對地址爲參數後面的內容
Retrofit和OkHttp同屬於Square公司的開源項目,這二者是互補的關係,OkHttp是一個實現了HTTP協議的客戶端,相似於HttpClient,而Retrofit是一個基於OkHttp的封裝庫,該庫主要簡化了http請求的實現過程,使得開發者只需關注自身功能的實現,而沒必要書寫那些比較冗餘的代碼。但也正是因爲Retrofit的高度封裝性,其擴展性就相對比較弱,某些比較靈活的功能還須要開發者本身經過OkHttp來實現。
Retrofit和Volley二者均是目前比較受開發者喜歡的兩個網絡庫,不過這二者仍是有比較大的差別。
Retrofit的底層實現是OkHttp,Volley的底層實現的是HttpClient和HttpUrlConnection;
Retrofit的返回能夠自動解析爲Java實體類,而Volley的返回數據類型根據請求類型而定(StringRequeset、ImageRequest、JsonObjectRequest或JsonArrayRequest),同時須要本身進行解析;
Retrofit擁有比較詳細的API文檔和比較活躍的社區支持,而google貌似並未給Volley提供開發文檔,只是在Android developers中的網絡部分有所說起,因此在易用性方面,感受Retrofit更勝一籌;
Retrofit支持動態生成URL,Volley好像並不支持;
二者均異步請求方式,這在Android應用中是很是重要的,由於Android程序中不容許在Home線程中執行網絡操做;