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(四)

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