RxHttp 一條鏈傳送請求之強大的Param類(三)

不怕天黑發表於2019-04-27

簡介

前面我們對RxHttp做了整體的介紹,我們知道,使用RxHttp庫傳送請求,有兩種方式。一種通過Param+HttpSender的形式,另外一種是直接使用RxHttp類,而RxHttp類內部其實就是通過Param+HttpSender實現的,我們可以理解為RxHttp類是Param的代理類。為此,本文將詳細講解Param類。

如果還未閱讀前面兩篇文章,請檢視

RxHttp 一條鏈傳送請求,新一代Http請求神器(一)

RxHttp 一條鏈傳送請求之強大的資料解析功能(二)

RxHttp 原始碼

Param結構

首先,附上一張Param類的繼承關係圖,下圖中藍色標註的為介面類。

RxHttp 一條鏈傳送請求之強大的Param類(三)
下面將對上圖中的常用類及方法做介紹。

Param介紹

在前文中,我們介紹了RxHttp的請求三部曲,如下:

  RxHttp.get("http://...")              //第一步,確定請求方式
        .asString()                     //第二步,確定返回型別
        .subscribe(s -> {               //第三部  訂閱觀察者
            //成功回撥
        }, throwable -> {
            //失敗回撥
        });
複製程式碼

而其中第一步,內部其實就是操作Param類,在這一步,我們不僅可以選擇請求方式,還可以新增引數、新增請求頭、新增檔案物件等常用的操作,下面詳細講解。

請求方式

首先,我們來看看Param都給我們提供了哪些請求方式:

在這裡插入圖片描述
上圖為Param提供的一系列靜態方法,看名字應該也能知道,其中get方法對應的就是Get請求,同理postXxxputXxx等方法就是對應的PostPut等請求,而考慮到Post等請求又可以有不同的形式,故提供了postFormpostJson方法,其中前者是表單形式,後者是Json形式。現實開發中,如果還有其它的形式的請求(如:傳送加密的請求),就需要我們自定義Param類,以滿足我們的業務需求,後續會講解。

現在我們來看看Param是怎麼定義的:

public interface Param extends IParam, IHeaders, IRequest {

    //Get請求
    static Param get(@NonNull String url) {
        return GetParam.with(url);
    }
    //Post請求,引數以Form表單鍵值對的形式提交
    static Param postForm(@NonNull String url) {
        return PostFormParam.with(url);
    }

    //省略其它方法
}
複製程式碼

可以看到Param就是一個介面,並且繼承了ParamBuilder、HeadersBuilder、NoBodyRequest、RequestBuilder這四個介面

新增請求引數

確定了請求方式後,我們就需要新增請求引數,RxHttp提供了3個方法:

//對引數的操作都在此介面裡
public interface IParam {
    //新增單個引數
    Param add(String key, Object value);

    //通過map新增多個引數
    Param add(Map<? extends String, ?> map);

    //設定json字串引數,呼叫此方法後,通過上面兩個add方法新增的引數將失效;非Json請求呼叫此方法無任何作用
    Param setJsonParams(String jsonParams);
    
   //省略若干方法
}
複製程式碼

第一個是新增單個引數,其中value是Object型別,故我們可以新增任意型別的引數,而不用進行強轉(這一點對於強迫症患者的我,真的很實用);第二個是通過map物件新增多個引數;第三個方法setJsonParams僅對Json形式的請求生效,如:postJsonputJsonpatchJsondeleteJson,此方法有兩點需要注意:

  • 非Json形式的請求呼叫此方法將不會產生任何作用
  • Json形式的請求呼叫此方法後,不管是之前還是後面通過add方法新增的引數都將失效

注:Param 內部是通過LinkedHashMap儲存引數。

新增請求頭

對請求頭的操作,都封裝在一個介面裡,程式碼如下:

public interface IHeaders {

    Headers getHeaders();

    String getHeader(String key);

    Headers.Builder getHeadersBuilder();

    Param setHeadersBuilder(Headers.Builder builder);

    Param addHeader(String key, String value);

    Param addHeader(String line);

    Param setHeader(String key, String value);

    Param removeAllHeader(String key);
}
複製程式碼

在上面的HeadersHeaders.Builder都是OkHttp內部提供的類,故可以知道在Param內部是通過Headers.Builder儲存的請求頭資訊。

新增檔案

Param內部目前僅提供了一個新增檔案的方法,如下:

//對引數的操作都在此介面裡
public interface IParam {
    /**
     * <p>新增檔案物件
     * <P>預設不支援,如有需要,自行擴充套件,參考{@link PostFormParam}
     *
     * @param key  鍵
     * @param file 檔案物件
     * @return Param
     */
    default Param add(String key, File file) {
        throw new UnsupportedOperationException("Please override if you need");
    }
   
    //省略若干方法
}
複製程式碼

可以看到,此方法預設會丟擲一個UnsupportedOperationException異常,即代表不支援這個操作,如果要支援,需要重寫此方法。目前RxHttp內部僅有postForm請求重寫了此方法,故僅有postForm請求支援檔案上傳,其它請求呼叫此方法,將直接丟擲異常;若自定義的請求要支援檔案上傳,請重寫此方法。

重新設定Url

我們知道,要拿到Param物件就必須呼叫相關靜態方法,並傳入url。然後現實開發中,我們可能需要動態更改url,又或者我們需要拿到當前url做一些判斷,為此RxHttp提供了相關方法,我們來看看

public interface IParam {

    Param setUrl(@NonNull String url);
}
複製程式碼
public interface IRequest {
    /**
     * @return 帶引數的url
     */
    String getUrl();
    /**
     * @return 不帶引數的url
     */
    String getSimpleUrl();
    
    //省略相關方法
}
複製程式碼

setUrl好理解,傳入一個url即可,需要特別說明的是getUrlgetSimpleUrl方法,其中前者會將引數以Get請求的形式拼接在url後面,並返回;而後者僅返回我們傳入的url物件。(在RxHttp庫內部,Get、Head請求會呼叫getUrl方法,其它請求皆呼叫getSimpleUrl方法)

自定義Param

從上面的結構圖,我們可以看到,RxHttp內部提供了4個類,不同形式及方式的請求,然後,現實開發中,它並不能滿足我們的業務場景,此時就需要我們自定義Param。看上圖我們知道,所有Param的具體實現類,都直接繼承與AbstractParam類,因此,我們要自定義Param,可以繼承AbstractParam類,當前也可根據自己的提交方式,直接繼承NoBodyParam、FormParam、JsonParam等。 例如,我們現在要傳送Post請求,引數已Json字串的形式提交,並且引數需要加密,那我們就可以直接繼承JsonParam類,如下:

public class PostEncryptJsonParam extends JsonParam {

    public PostEncryptJsonParam(String url) {
        super(url, Method.POST);
    }

    /**
     * @return 根據自己的業務需求返回對應的RequestBody
     */
    @Override
    public RequestBody getRequestBody() {
        return null;
    }
}
複製程式碼

可以看到,我們只需要實現一個getRequestBody()方法,並返回一個RequestBody物件即可,我們再來看看實現

@Param(methodName = "postEncryptJson")
public class PostEncryptJsonParam extends JsonParam {

    private static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8");

    public PostEncryptJsonParam(String url) {
        super(url, Method.POST);
    }

    /**
     * @return 根據自己的業務需求返回對應的RequestBody
     */
    @Override
    public RequestBody getRequestBody() {
        //我們要傳送Post請求,引數以加密後的json形式發出
        //第一步,將引數轉換為Json字串
        JsonObject jsonObject = BuildUtil.mapToJson(this);
        String json = jsonObject.toString();
        //第二步,加密
        byte[] encryptByte = encrypt(json, "RxHttp");
        //第三部,建立RequestBody並返回
        RequestBody requestBody = RequestBody.create(MEDIA_TYPE_JSON, encryptByte);
        return requestBody;
    }

    /**
     * @param content  要加密的字串
     * @param password 密碼
     * @return 加密後的位元組陣列
     */
    private byte[] encrypt(String content, String password) {
        //加密程式碼省略
        return null;
    }
}
複製程式碼

可以看到,非常簡單,首先將引數轉換為Json字串,然後進行加密,最後根據加密後的資料建立RequestBody物件並返回即可,現在我們來看看如何使用PostEncryptJsonParam這個類。

注:我們在PostEncryptJsonParam類上使用了註解@Param(methodName = "postEncryptJson"),Rebuild一下專案,就會在RxHttp類下生成一個static RxHttp postEncryptJson(String url)的靜態方法。 關於註解的使用,請檢視RxHttp 一條鏈傳送請求之註解處理器 Generated API(四) 此時我們就可以這麼做

  String url = "http://www....";
  RxHttp.postEncryptJson(url)  //postEncryptJson 是使用註解生成的方法
        .add("key1", "value1")
        .add("key2", "value3")//新增引數
        .asResponse(Address.class) //asXXX操作符,是非同步操作
        .as(RxLife.asOnMain(this)) //感知生命週期,並在主執行緒回撥
        .subscribe(address -> {
            //accept方法引數型別由上面DataParser傳入的泛型型別決定
            //走到這裡說明Http請求成功,並且資料正確
        }, throwable -> {
            //Http請求出現異常,有可能是網路異常,資料異常等
        });
複製程式碼

可以看到,使用RxHttp.postEncryptJson(url)靜態方法得到PostEncryptJsonParam物件,並新增相關引數即可,其它邏輯沒有任何改變。

小結

到這,你會發現,Param在RxHttp庫中是一個非常重要的角色,它提供了非常多簡單易用的Api,這使得RxHttp非常的好用。

最後,本文如果有寫的不對的地方,請廣大讀者指出。 如果覺得我寫的不錯,記得給我點贊RxHttp

轉載請註明出處,謝謝? 註解使用請檢視

RxHttp 一條鏈傳送請求之註解處理器 Generated API(四)

相關文章