咱們在使用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的話,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
可是咱們在使用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信息。
咱們能夠這麼定義接口
@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 { * @GET("user/me") * Observable<User> 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的源碼實在是太晦澀難懂了