Retrofit:聲明 ApiService接口

Retrofit:聲明 ApiService接口

咱們在使用Retrofit的時候只須要把URL經過註解的形式寫到APIService文件中就好了。java

好比登陸功能:api

若是後臺的成功返回格式爲網絡

{    
    code:0;
    Message:"login success"
}

失敗的返回格式爲app

{    
    code:-1;
    Message:"login failed"
}

咱們定義個一個Bean類LoginResult.異步

public class LoginResult{
    private int code;
    private String message;
    
    //get/set
}

不使用Rxjava

在方法的定義中,若是不適用Rxjava的話,ide

@Post
@FormUrlEncoded
Call<LogInResult> login(@Field("userName") String userName, @Field("password")String password);

在使用的時候們只須要使用apiService.login("dsf", "dsf"),就行了。該方法會返回一個Call<LoginResult> 對象源碼分析

咱們只須要或者異步執行post

//同步執行
Response<LoginResult> response = call.execute();
//異步調用
call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {

            }
        });

而後咱們在返回結果裏面操做就好了,若是咱們須要Response裏面的元數據,好比header裏面的信息的話,直接從Response取就行了。ui

由於Retrofit 使用DefaultCallAdapterFactory默認將OKHttp返回的Call對象(OkHttp對象)轉換成了Retrofit的Call<T>對象了this

使用Rxajva

Observable<T>

可是咱們在使用RxJava後,有時可能會這樣聲明接口

@Post
@FormUrlEncoded
Observable<LogInResult> login(@Field("userName") String userName, @Field("password")String password);

這樣定義能夠很方便的在返回中直接subScribe一個Action對象了

Observable<LoginResult> observable = model.login("dfs", "dfs");
observable.subscribe(new Action1<LoginResult>() {
            @Override
            public void call(LoginResult loginResult) {
                if (loginResult.getCode() == 0) {
                    //登陸成功   
                } else {
                    //登陸失敗
                }
                    
            }
        });

可是這樣有一個問題就是會丟失Response的元數據,由於Response對象咱們是無法訪問的。由於Retrofit已經幫助咱們作了轉換,直接把咱們接口方法裏定義的數據類型轉換好後返回給咱們了。去掉了Response信息。

Observable<Response<T>>

咱們能夠這麼定義接口

@Post
@FormUrlEncoded
Observable<Response<LogInResult>> login(@Field("userName") String userName, @Field("password")String password);

這樣咱們就獲得這樣的返回結果。

Observable<Response<LoginResult>> observable = model.login("dfs", "dfs");
observable.subscribe(new Action1<Response<LoginResult>>() {
            @Override
            public void call(Response<LoginResult> loginResultResponse) {
                if (loginResultResponse.code() == 200){
                    LoginResult body = loginResultResponse.body();
                }else {
                    //登陸失敗
                }
            }
        });

這樣就能拿到Response信息了,而後根據Response code判斷是否登陸成功了。

可是這樣有個問題是咱們寫接口會特備繁瑣,每次都得使用Response<>泛型。通常咱們都寫做Observable<LoginResult> login();

其實咱們通常狀況下也不關注Response信息的。可是不排除特殊狀況

好比這種狀況

https://academy.realm.io/cn/p...

這篇文章提到的分頁加載的狀況,其實這種狀況也能夠將下一個頁面的URL放到Response body裏返回。

這裏只是給出了一種情景。

現實中解決方案不少種,只能折中了,其實咱們不必使用Response的Response code 來判斷接口是否調用成功了。由於Retrofit都幫咱們作過了。因此咱們定義接口的時候只要使用Observable<Bean>就行了。

咱們在使用Retrofit + Rxjava 的時候通常都這麼生成Retrofit client的

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

這裏RxJavaCallAdapterFactory生成的CallAdapter對象就幫咱們作好告終果的轉換

咱們看一下RxJavaCallAdapterFactory的聲明。

/**
 * A {@linkplain CallAdapter.Factory call adapter} which uses RxJava for creating observables.
 * <p>
 * Adding this class to {@link Retrofit} allows you to return {@link Observable} from service
 * methods.
 * <pre><code>
 * interface MyService {
 *   &#64;GET("user/me")
 *   Observable&lt;User&gt; getUser()
 * }
 * </code></pre>
 * There are three configurations supported for the {@code Observable} type parameter:
 有三種配置支持Observable的類型參數
 * <ul>
 * <li>Direct body (e.g., {@code Observable<User>}) calls {@code onNext} with the deserialized body
 * for 2XX responses and calls {@code onError} with {@link HttpException} for non-2XX responses and
 * {@link IOException} for network errors.</li>
 第一種:直接使用Observable<T>聲明接口, 將會針對全部的2** Response code會調用onNext(T t)方法。全部的Response code 不是200的都調用OnError(Throwable t)方法拋出一個HttpException 異常,網絡錯誤調用onError()方法,並拋出一個IO異常。
 
 * <li>Response wrapped body (e.g., {@code Observable<Response<User>>}) calls {@code onNext}
 * with a {@link Response} object for all HTTP responses and calls {@code onError} with
 * {@link IOException} for network errors</li>
 第二種:若是使用Observable<Response<T>>聲明接口,那麼針對全部的Response將會調用onNext(Respones<T> response)方法,針對網絡異常將調用OnError()方法,並拋出一個IO異常。
 * <li>Result wrapped body (e.g., {@code Observable<Result<User>>}) calls {@code onNext} with a
 * {@link Result} object for all HTTP responses and errors.</li>
 第三種:若是使用Observable<Result<T>聲明接口。全部的Response和Error將會調用onNext方法。
 注意:這個Result是Retrofit提供的。
 * </ul>
 */

結論

結論就是,若是咱們沒有對Response有特殊的需求的話,直接在接口聲明處直接聲明成Observable<T>是最方便最直觀的。

這篇文章本應該和Retofit源碼分析一塊兒寫的,奈何Retrofit的源碼實在是太晦澀難懂了

相關文章
相關標籤/搜索