框架學習| Retrofit2.x(一)

釐米姑娘發表於2018-07-04

開新坑辣!一直覺得自己框架了解的特別少,大多隻知其名而不知實現原理,然而幾乎每次面試都會被問及框架。所以很有必要總結一些常用的框架,希望自己能堅持把這個『框架學習』系列的新坑填的厚實一點!

先從網路框架中大名鼎鼎的Retrofit開始吧,本篇先對Retrofit有個瞭解,目錄如下:

  • 概述
  • 使用方式

1.概述

a.Retrofit是Square公司推出的一個基於RESTful風格的HTTP網路框架。

相關連結地址:

b.與OkHttp的關係:

是對OkHttp網路請求框架的二次封裝,本質仍是OkHttp。即網路請求的工作本質上是由OkHttp完成,而Retrofit僅負責網路請求介面的封裝。流程如圖:

框架學習| Retrofit2.x(一)

  • 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);
}
複製程式碼

常用的註解含義如圖:

框架學習| Retrofit2.x(一)

這裡可以發現,@GET和@Query搭配使用,@POST和@Field搭配使用。


step4:建立Retrofit物件並設定資料解析器

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("URL") //設定網路請求的Url地址,注意以要以斜線(代表根目錄)結尾
                .addConverterFactory(GsonConverterFactory.create()) //設定資料解析器,這裡表示用的是JSON解析返回值
                .build();
複製程式碼

常用的資料解析器如圖:

框架學習| Retrofit2.x(一)


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可根據不同的介面定義,靈活地生成對應的網路工作物件,然後利用這個物件去訪問網路。它就像一個工廠,只提供產品,本身不處理網路請求,而是讓產品去處理網路請求。

框架學習| Retrofit2.x(一)

下一篇將進行Retrofit的原始碼分析~

相關文章