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

簡介

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

如果還未閱讀前面兩篇文章,請查看

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

RxHttp 一條鏈發送請求之強大的數據解析功能(二)

RxHttp庫已更新至1.0.3版本,詳情請查看RxHttp 源碼

Param結構

首先,附上一張Param類的繼承關係圖,下圖中藍色標註的爲接口類。
在這裏插入圖片描述
下面將對上圖中的常用類及方法做介紹。

Param介紹

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

  RxHttp.get("http://...")                //第一步,確定請求方式
        .fromSimpleParser(String.class) //  第二步,確定解析器
        .subscribe(s -> {               //第三部  訂閱觀察者
            //成功回調
        }, throwable -> {
            //失敗回調
        });

而其中第一步,內部其實就是操作Param類,在這一步,我們不僅可以選擇請求方式,還可以添加參數、添加請求頭、添加文件對象等常用的操作,下面詳細講解。

請求方式

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

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

public interface Param extends ParamBuilder, HeadersBuilder, NoBodyRequest, RequestBuilder {

    //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 ParamBuilder {
    //添加單個參數
    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 HeadersBuilder {

    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 ParamBuilder {
    /**
     * <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 ParamBuilder {

    Param setUrl(@NonNull String url);
}
public interface NoBodyRequest {
    /**
     * @return 帶參數的url
     */
    String getUrl();
    /**
     * @return 不帶參數的url
     */
    String getSimpleUrl();
    
    //省略相關方法
}

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

自定義Param

從上面的結構圖,我們可以看到,RxHttp內部提供了10個類,不同形式及方式的請求,然後,現實開發中,它並不能滿足我們的業務場景,此時就需要我們自定義Param。看上圖我們知道,所有Param的具體實現類,都間接繼承與AbstractParam類,而對於同一種請求,例如PostFormParamPostJsonParam都繼承於AbstractPostParam。因此,我們要自定義Param,可以繼承AbstractXxxParam類即可。
例如,我們現在要實現一個Post請求,參數以加密後的Json字符串發出,代碼就可以這些寫

public class PostEncryptJsonParam extends AbstractPostParam {

    public PostEncryptJsonParam(String url) {
        super(url);
    }

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

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

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

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

    public PostEncryptJsonParam(String url) {
        super(url);
    }

    /**
     * @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")//添加參數
        .fromDataParser(Address.class) //from操作符,是異步操作
        .as(RxLife.asOnMain(this)) //感知生命週期,並在主線程回調
        .subscribe(address -> {
            //accept方法參數類型由上面DataParser傳入的泛型類型決定
            //走到這裏說明Http請求成功,並且數據正確
        }, throwable -> {
            //Http請求出現異常,有可能是網絡異常,數據異常等
        });

可以看到,使用RxHttp.postEncryptJson(url)靜態方法得到PostEncryptJsonParam對象,並添加相關參數即可,其它邏輯沒有任何改變。

到這,我可以告訴你,AbstractPostParam、AbstractPutParam、AbstractPatchParam、AbstractDeleteParam這4個抽象類,其實是一樣的邏輯,都只需要實現getRequestBody()方法即可。

小結

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

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

轉載請註明出處,謝謝?
註解使用請查看

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章