Android網絡訪問庫 - Retrofit學習(1)基礎

Retrofit是什麼

Retrofit是一個類型安全的HTTP客戶端,支持Android和Java.它是Square公司開源的項目,當前版本2.0。java

在實際開發中,咱們Retrofit配合OKHTTP來使用。咱們使用OKHTTP當作傳輸層,使用Retrofit在OKHTTP之上,使用Java的接口描述咱們的HTTP協議。
簡單的說: 使用Retrofit轉換HTTP 的API協議成一個java的Interface服務,咱們直接使用java類會方便好多。react

Github: https://github.com/square/retrofitandroid

當前版本2.1,本文會對比1.9來說述2.x的特性。git

Retrofit特色

  • Retrofit將HTTP的API轉換成java接口,並對接口生成默認的實現類。
  • 支持同步和異步的調用方式
  • 使用註解描述HTTP請求
  • 對象轉換,好比從json轉換成java對象
  • 支持多請求體(Multipart request body)和文件上傳

類庫和引用

添加依賴

在你的應用級別的gradle中添加:github

compile 'com.squareup.retrofit2:retrofit:2.1.0'

通常狀況下,咱們還須要處理json格式的數據,那麼咱們須要一個轉換器,你須要增長下面的依賴:web

compile 'com.squareup.retrofit2:converter-gson:2.1.0'

集成OKHTTP

爲了不重複引用OKHTTP,你還能夠這麼使用:數據庫

compile ('com.squareup.retrofit2:retrofit:2.1.0') {  
  // 排除依賴okhttp
  exclude module: 'okhttp'
}
compile 'com.squareup.okhttp3:okhttp:3.3.1' //從新依賴okhttp

集成rxJava

若是你還想配合rxJava使用,你須要添加依賴:json

compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'  
compile 'io.reactivex:rxandroid:1.0.1'

在Retrofit2.x, RestAdapter 被改變爲 Retrofit

Retrofit 1.9 時的寫法api

RestAdapter.Builder builder = new RestAdapter.Builder();

Retrofit 2.x的寫法安全

Retrofit.Builder builder = new Retrofit.Builder();

配置URL地址

基礎BaseUrl

基礎url,就是你的服務器的地址,通常是個域名。好比你要訪問 http://www.xxxx.com/user/list
咱們在開發中使用相對url,即 /user/list,那麼它的baseUrl就是 http://www.xxx.com
咱們這樣設置 baseUrl:

Retrofit retrofit = Retrofit.Builder()  
    .baseUrl(API_BASE_URL);
    .build();

YourService service = retrofit.create(YourService.class);

Retrofit建議咱們在設置 baseUrl時,以「/" 結尾。這樣咱們在指定相對路徑的時候就不用寫"/"了。
像下面這樣:

public interface UserService {  
    @POST("me") //注意這裏,沒有 斜槓開頭
    Call<User>me();
}

Retrofit retrofit = Retrofit.Builder()  
    .baseUrl("https://your.api.url/v2/");//注意這裏,以 斜槓結尾
    .build();

UserService service = retrofit.create(UserService.class);

// the request url for service.me() is: 
// https://your.api.url/v2/me

動態的url

有時候咱們會以一些其餘方式得到一個url,好比從數據庫或者網絡讀取到一個url,這樣的url就不能像上面那樣 經過 baseUrl和相對url組合而成。
咱們可使用 "@Url" 註解來作,使用"@Url"對一個方法的參數進行註解,代表這是個url,示例:

public interface UserService {  
    @GET
    public Call<File> getZipFile(@Url String url);
}

由OKHTTP驅動的攔截器Interceptors

使用攔截器處理自定義請求是一種頗有用的方式。步驟:
1.自定義一個攔截器Interceptor
2.自定義一個OkHttpClient,調用 addInterceptor 方法,傳入上面的攔截器
3.在構建Retrofit時, Retrofit.Builder 中,使用 .client() 方法. 傳入OkHttpClient
示例:

OkHttpClient.Builder httpClient = new OkHttpClient.Builder();  
httpClient.addInterceptor(new Interceptor() {  
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request original = chain.request();

        // Customize the request 
        Request request = original.newBuilder()
                .header("Accept", "application/json")
                .header("Authorization", "auth-token")
                .method(original.method(), original.body())
                .build();

        Response response = chain.proceed(request);

        // Customize or return the response 
        return response;
    }
});

OkHttpClient client = httpClient.build();  
Retrofit retrofit = Retrofit.Builder()  
    .baseUrl("https://your.api.url/v2/");
    .client(client)
    .build();

請求的調用。 同步和異步,和終止

Retrofit 1.x 時,在服務接口的聲明中,同步方法須要一個返回值,異步方式須要一個 Callback 的泛型參數做爲最後一個參數。
而在 2.x 時,再也不區分同步和異步調用,都被包裹在 一個泛型Call類中。
下面咱們從 「接口定義」 和 「調用」 來對比他們的不一樣。

「接口定義」的區別

Retrofit 1.9 時

public interface UserService {  
    // 同步,有返回值
    @POST("/login")
    User login();

    // 異步 Request,最後一個參數是 Callback 泛型
    @POST("/login")
    void getUser(@Query String id, Callback<User> cb);
}

而在 Retrofit 2.x 時

public interface UserService {  
    @POST("/login")
    Call<User> login();
}

注意上面返回了一個Call的泛型。2.x再也不以參數和返回值的方式區分異步同步的請求。

「調用」的區別

Retrofit 1.9 時
同步是直接調用。
而異步須要傳入回調的實現。在實現裏處理成功和失敗的方法。

// 同步
User user = userService.login();

// 異步
userService.login(new Callback<User>() {  
@Override
    public void success(User user, Response response) {
        // handle response
    }

    @Override
    public void failure(RetrofitError error) {
        // handle error
    }
});

而在 Retrofit 2.x 時
同步是 調用 call.execute() 來得到結果。
異步是 調用 enqueue方法和傳入回調。注意這裏的回調 是onResponse 方法,不一樣於上面的成功和失敗的方法。
這裏的是onResponse 方法使用 response.isSuccessful()判斷成功和失敗。若是失敗,使用 errorBody得到錯誤信息。

// 同步
Call<User> call = userService.login();  
User user = call.execute().body();

// 異步
Call<User> call = userService.login();  
call.enqueue(new Callback<User>() {  
    @Override
    public void onResponse(Call<User> call, Response<User> response) {
        // response.isSuccessful() is true if the response code is 2xx
        if (response.isSuccessful()) {
            User user = response.body();
        } else {
            int statusCode = response.code();

            // handle request errors yourself
            ResponseBody errorBody = response.errorBody();
        }
    }

    @Override
    public void onFailure(Call<User> call, Throwable t) {
        // handle execution failures like no internet connectivity 
    }
}

取消/終止請求

在 Retrofit 1.9 是沒法終止請求的。而在2.x ,你可使用 cancel 來終止請求。

Call<User> call = userService.login();  
User user = call.execute().body();

// changed your mind, cancel the request
call.cancel();

轉換器

選擇你須要的轉換器

對比1.9提供默認的json轉換器,Retrofit 2.x之後不在提供默認的轉換器。好比你要使用json解析,
你可使用gson轉換器,添加庫依賴:

compile 'com.squareup.retrofit2:converter-gson:2.1.0'

Retrofit支持不少種轉換器類型,根據你的須要,你能夠經過gradle引用不一樣的擴展庫:

Gson: com.squareup.retrofit2:converter-gson:2.1.0
Moshi: com.squareup.retrofit2:converter-moshi:2.1.0
Jackson: com.squareup.retrofit2:converter-jackson:2.1.0
SimpleXML: com.squareup.retrofit2:converter-simplexml:2.1.0
ProtoBuf: com.squareup.retrofit2:converter-protobuf:2.1.0
Wire: com.squareup.retrofit2:converter-wire:2.1.0

若是上面的轉換器還不夠你使用的話,你能夠經過本身實現 Converter.Factory 來自定義轉換器。

添加轉換器到Retrofit對象

咱們須要手動添加轉換器到Retrofit對象上,使用addConverterFactory方法來添加一個ConverterFactory對象到Retrofit。

  • 你能夠根據你的須要選擇不一樣的 轉換器工廠(ConverterFactory).
  • 你能夠添加一個或者多個ConverterFactory,順序很重要,Retrofit將會按順序使用它,若是失敗,就嘗試使用下一個轉換器。

示例:

Retrofit retrofit = Retrofit.Builder()  
    .baseUrl("https://your.api.url/v2/");
    .addConverterFactory(ProtoConverterFactory.create())
    .addConverterFactory(GsonConverterFactory.create())
    .build();

自定義轉換器

請閱讀 Retrofit converter implementations

集成 RxJava

依賴

Retrofit 1.9 集成了三種請求執行機制: 同步,異步,RxJava。而到了2.x後,僅僅保留了同步和異步機制。
Retrofit 2.x 提供了一種插件擴展的機制支持RxJava。要集成RxJava,你須要添加如下兩個依賴,
第一個依賴是 CallAdapter 它以一種新的方式處理請求。你可使用 Observable 做爲接口聲明的返回值。
第二個依賴是 AndroidSchedulers 類所須要的,它提供了 在Android主線程的調度方式。

compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'  
compile 'io.reactivex:rxandroid:1.0.1'

使用

在構建Retrofit實例時,經過 addCallAdapterFactory 方法傳入 CallAdapter。

Retrofit retrofit = new Retrofit.Builder()  
    .baseUrl(baseUrl);
    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
    .addConverterFactory(GsonConverterFactory.create())
    .build();

接口聲明時,返回一個 Observable 泛型對象。

public interface UserService {  
    @POST("/me")
    Observable<User> me();
}

// this code is part of your activity/fragment
Observable<User> observable = userService.me();  
observable  
        .observeOn(AndroidSchedulers.mainThread())
        .subscribeOn(Schedulers.io())
        .subscribe(new Subscriber<User>() {
    @Override
    public void onCompleted() {
        // 處理完成
    }

    @Override
    public void onError(Throwable e) {
        // 處理異常
    }

    @Override
    public void onNext(User user) {
        // 處理響應結果
    }
});

不包含默認日誌

Retrofit 自己沒有提供日誌功能,不過咱們能夠經過自定義okhttp的攔截器來實現它。你能夠閱讀這篇文章:
on how to get back logging into Retrofit 2

更新特性 WebSockets

Retrofit不提供 WebSockets 功能,不過OKHTTP提供了 WebSockets支持。

擴展資源

Jake Wharton’s talk @ Droidcon NYC 2015 on Retrofit 2
Details on OkHttp interceptors
Retrofit Converters
RxAndroid on GitHub
Retrofit CallAdapters
Retrofit Change Log

相關文章
相關標籤/搜索