2024年HarmonyOS鸿蒙最全RxHttp 让你眼前一亮的Http请求框架(4),2024年最新小红书软件测试面试

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

implementation 'com.github.liujingxing.rxhttp:rxhttp:2.7.3'
kapt 'com.github.liujingxing.rxhttp:rxhttp-compiler:2.7.3' //生成RxHttp类,纯Java项目,请使用annotationProcessor代替kapt

}


#### 可选



android {
kapt {
arguments {
//依赖了RxJava时,rxhttp_rxjava参数为必须,传入RxJava版本号
arg(“rxhttp_rxjava”, “3.1.1”)
arg(“rxhttp_package”, “rxhttp”) //指定RxHttp类包名,非必须
}
}
//如果项目未集成kotlin,通过javaCompileOptions方法传参,在defaultConfig标签下
annotationProcessorOptions {
arguments = [
rxhttp_rxjava: ‘3.1.1’,
rxhttp_package: ‘rxhttp’
]
}
}
dependencies {
//rxjava2 (RxJava2/Rxjava3二选一,使用asXxx方法时必须)
implementation ‘io.reactivex.rxjava2:rxjava:2.2.8’
implementation ‘io.reactivex.rxjava2:rxandroid:2.1.1’
implementation ‘com.github.liujingxing.rxlife:rxlife-rxjava2:2.2.1’ //管理RxJava2生命周期,页面销毁,关闭请求

//rxjava3
implementation 'io.reactivex.rxjava3:rxjava:3.1.1'
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
implementation 'com.github.liujingxing.rxlife:rxlife-rxjava3:2.2.1' //管理RxJava3生命周期,页面销毁,关闭请求

//非必须,根据自己需求选择 RxHttp默认内置了GsonConverter
implementation 'com.github.liujingxing.rxhttp:converter-fastjson:2.7.3'
implementation 'com.github.liujingxing.rxhttp:converter-jackson:2.7.3'
implementation 'com.github.liujingxing.rxhttp:converter-moshi:2.7.3'
implementation 'com.github.liujingxing.rxhttp:converter-protobuf:2.7.3'
implementation 'com.github.liujingxing.rxhttp:converter-simplexml:2.7.3'

}


`注:添加依赖后,需要rebuild一下项目,注解处理器才会生成RxHttp类; 另外kotlin用户,请使用kapt替代annotationProcessor`


最后,Rebuild一下项目(必须的),就会自动生成RxHttp类


以上步骤后,还未生成RxHttp类,请查看[RxHttp类没有生成,检查步骤]( )


### 3.2、配置默认的BaseUrl


通过`@DefaultDomain`注解配置默认域名,如下:



public class Url {
@DefaultDomain //设置为默认域名
public static String baseUrl = “https://www.wanandroid.com/”;
}


此步骤是非必须的,这里先介绍`@DefaultDomain`注解的用法,更多有关域名的介绍,请查看本文3.6章节----多域名/动态域名


### 3.3、请求三部曲


![1.jpg](https://img-blog.csdnimg.cn/img_convert/476eccb0088c5f6be0ed95afb721c265.png)


***注:`RxHttp + 协程`文档,请查看[RxHttp ,比Retrofit 更优雅的协程体验]( )***


代码表示,发送一个最简单的请求,如下



RxHttp.get(“http://…”) //第一步, 通过get、postXxx、putXxx等方法,确定请求类型
.asString() //第二步, 通过asXxx系列方法,确定返回数据类型
.subscribe(s -> { //第三步, 订阅回调(此步骤同RxJava订阅观察者)
//请求成功
}, throwable -> {
//请求失败
});


是的,不用怀疑,就是这么简单,重要的事情说3遍


**任意请求,任意返回数据类型,皆遵循请求三部曲**


**任意请求,任意返回数据类型,皆遵循请求三部曲**


**任意请求,任意返回数据类型,皆遵循请求三部曲**


到这,你已经掌握了[RxHttp]( )的精髓,我们只需牢记请求三部曲,使用RxHttp就会得心应手。


#### 3.3.1、第一部曲:确定请求类型


RxHttp内部共提供了14个请求方法,如下:



RxHttp.get(String) //get请求 参数拼接在url后面
RxHttp.head(String) //head请求 参数拼接在url后面
RxHttp.postForm(String) //post请求 参数以{application/x-www-form-urlencoded}形式提交
RxHttp.postJson(String) //post请求 参数以{application/json; charset=utf-8}形式提交,发送Json对象
RxHttp.postJsonArray(String) //post请求 参数以{application/json; charset=utf-8}形式提交,发送Json数组
RxHttp.putForm(String) //put请求 参数以{application/x-www-form-urlencoded}形式提交
RxHttp.putJson(String) //put请求 参数以{application/json; charset=utf-8}形式提交,发送Json对象
RxHttp.putJsonArray(String) //put请求 参数以{application/json; charset=utf-8}形式提交,发送Json数组
RxHttp.patchForm(String) //patch请求 参数以{application/x-www-form-urlencoded}形式提交
RxHttp.patchJson(String) //patch请求 参数以{application/json; charset=utf-8}形式提交,发送Json对象
RxHttp.patchJsonArray(String) //patch请求 参数以{application/json; charset=utf-8}形式提交,发送Json数组
RxHttp.deleteForm(String) //delete请求 参数以{application/x-www-form-urlencoded}形式提交
RxHttp.deleteJson(String) //delete请求 参数以{application/json; charset=utf-8}形式提交,发送Json对象
RxHttp.deleteJsonArray(String) //delete请求 参数以{application/json; charset=utf-8}形式提交,发送Json数组


以上14个请求方法你会发现,其实就6个类型,分别对应是Get、Head、Post、Put、Patch、Delete方法,只是其中Post、Put、Patch、Delete各有3个方法有不同形式的提交方式,只需要根据自己的需求选择就好。


如以上方法还不能满足你的需求,我们还可以通过`@Param`注解自定义请求方法,有关注解的使用,本文后续会详细介绍。


`注:当调用xxxForm方法发送请求时,通过setMultiForm()方法或者调用addFile(String, File)添加文件时,内部会自动将参数以{multipart/form-data}方式提交`


**添加参数/请求头**


确定请求方法后,我们就可以调用一系列`addXxx()`方法添加参数/请求头,如下:



RxHttp.get(“/service/…”) //发送get请求
.add(“key”, “value”) //添加参数
.addAll(new HashMap<>()) //通过Map添加多个参数
.addHeader(“deviceType”, “android”) //添加请求头


任意请求,都可调用以上3个方法添加参数/请求头,当然,在不同的请求方式下,也会有不同的addXxx方法供开发者调用。如下:



//postJson请求方法下会有更多addAll等方法可供调用
RxHttp.postJson(“/service/…”) //发送post Json请求
.addAll(new JsonObject()) //通过json对象添加多个参数
.addAll(“{“height”:180,“weight”:70}”) //通过json字符串添加多个参数

//postForm请求方法下会有一系列addFile方法可供调用
RxHttp.postForm(“/service/…”) //发送post表单请求
.addFile(“file”, new File(“xxx/1.png”)) //添加单个文件
.addFiles(“fileList”, new ArrayList<>()) //添加多个文件


以上只列出了几个常用的addXxx方法,更多方法请下载源码体验。


#### 3.3.2、第二部曲:确定返回数据类型


添加好参数/请求头后,正式进入第二部曲,确定返回数据类型,我们通过`asXxx`方法确定返回类型,比如,我们要返回一个Student对象,就可以通过`asClass(Class<T>)`方法,如下:



RxHttp.postForm(“/service/…”) //发送post表单请求
.add(“key”, “value”) //添加参数,可调用多次
.asClass(Student.class) //返回Student类型
.subscribe(student -> {
//请求成功,这里就能拿到 Student对象
}, throwable -> {
//请求失败
});


如果要返回Student对象列表,则可以通过`asList(Class<T>)`方法,如下:



RxHttp.postForm(“/service/…”) //发送post表单请求
.add(“key”, “value”) //添加参数,可调用多次
.asList(Student.class) //返回List类型
.subscribe(students -> {
//请求成功,这里就能拿到 Student对象列表
}, throwable -> {
//请求失败
});


**解析`Response<T>`类型数据**


然而,现实开发中,大多数人的接口,返回的数据结构都类似下面的这个样子



public class Response {
private int code;
private String msg;
private T data;
//这里省略get、set方法
}


对于这种数据结构,按传统的写法,每次都要对code做判断,如果有100个请求,就要判断100次,真的会逼死强迫症患者。


RxHttp对于这种情况,给出完美的答案,比如`Response<T>`里面的T代表一个Student对象,则可以通过`asResponse(Class<T>)`方法获取,如下:



RxHttp.postForm(“/service/…”) //发送post表单请求
.add(“key”, “value”) //添加参数,可调用多次
.asResponse(Student.class) //返回Student类型
.subscribe(student -> {
//请求成功,这里能拿到 Student对象
}, throwable -> {
//请求失败
});


如果`Response<T>`里面的T代表一个`List<Student>`列表对象,则可以通过`asResponseList(Class<T>)`方法获取,如下



RxHttp.postForm(“/service/…”) //发送post表单请求
.add(“key”, “value”) //添加参数,可调用多次
.asResponseList(Student.class) //返回List类型
.subscribe(students -> {
//请求成功,这里能拿到List列表对象
}, throwable -> {
//请求失败
});


更多时候,我们的列表数据是分页的,类似下面的数据结构



{
“code”: 0,
“msg”: “”,
“data”: {
“totalPage”: 0,
“list”: []
}
}


此时,调用RxHttp的`asResponsePageList(Class<T>)`方法依然可以完美解决,如下:



RxHttp.postForm(“/service/…”) //发送post表单请求
.add(“key”, “value”) //添加参数,可调用多次
.asResponsePageList(Student.class) //返回PageList类型
.subscribe(pageList -> {
//请求成功,这里能拿到PageList列表对象
int totalPage = pageList.getTotalPage(); //总页数
List students = pageList.getData(); //单页列表数据
}, throwable -> {
//请求失败
});


到这,估计很多人会问我:


* 你的code在哪里判断的?
* 我的code是100或者其它值才代表正确,怎么改?
* 我的`Response<T>`类里面的字段名,跟你的都不一样,怎么该?
* 你这成功的时候直接返回`Response<T>`里面的T,那我还要拿到code做其他的判断,执行不同业务逻辑,怎么办?


这里可以先告诉大家,`asResponse(Class<T>)`、`asResponseList(Class<T>)`、`asResponsePageList(Class<T>)`这3个方法并不是RxHttp内部提供的,而是通过自定义解析器生成,里面的code判断、`Response<T>`类都是开发者自定义的,如何自定义解析器,请查看本文5.1章节----自定义Parser。


接着回答第4个问题,如何拿到code做其他的业务逻辑判断,很简单,我们只需用`OnError`接口处理错误回调即可,如下:



RxHttp.postForm(“/service/…”) //发送post表单请求
.add(“key”, “value”) //添加参数,可调用多次
.asResponse(Student.class) //返回Student类型
.subscribe(student -> {
//请求成功,这里能拿到 Student对象
}, (OnError) error -> { //注意,这里要用OnError接口,其中error是一个ErrorInfo对象
//失败回调
//拿到code字段,此时就可以对code做判断,执行不同的业务逻辑
int code = error.getErrorCode();
String errorMsg = error.getErrorMsg() //拿到msg字段
});


`注:上面的OnError接口并非是RxHttp内部提供的,而是自定义的,在Demo里可以找到`


以上介绍的5个asXxx方法,可以说基本涵盖80%以上的业务场景,RxHttp内部提供了一系列`asXxx`方法,如,`asInteger、asBoolean、asLong、asBitmap、asList、asMap`等等,它们最终都是通过`asParser(Parser<T>)`方法实现的,具体实现过程,这里先跳过,后续会详细讲解。


#### 3.3.3、第三部曲:订阅回调


这一步就很简单了,在第二部曲中,asXxx方法会返回`Observable<T>`对象,没错,就是RxJava内部的`Observable<T>`对象,此时我们便可通过`subscribe`系列方法订阅回调,如下:



//不处理任何回调
RxHttp.postForm(“/service/…”) //发送post表单请求
.add(“key”, “value”) //添加参数,可调用多次
.asResponseList(Student.class) //返回List类型
.subscribe(); //不订阅任何回调

//仅订阅成功回调
RxHttp.postForm(“/service/…”) //发送post表单请求
.add(“key”, “value”) //添加参数,可调用多次
.asResponseList(Student.class) //返回List类型
.subscribe(students -> {
//请求成功,这里能拿到List列表对象
});

//订阅成功与失败回调
RxHttp.postForm(“/service/…”) //发送post表单请求
.add(“key”, “value”) //添加参数,可调用多次
.asResponseList(Student.class) //返回List类型
.subscribe(students -> {
//请求成功,这里能拿到List列表对象
}, throwable -> {
//请求失败
});

//等等,省略


另外,我们还可以订阅请求开始/结束的回调,如下:



RxHttp.get(“/service/…”)
.asString()
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe(disposable -> {
//请求开始,当前在主线程回调
})
.doFinally(() -> {
//请求结束,当前在主线程回调
})
.as(RxLife.as(this)) //感知生命周期
.subscribe(s -> {
//成功回调,当前在主线程回调
}, (OnError) error -> {
//失败回调,当前在主线程回调
});


到这,请求三部曲介绍完毕,接着,将介绍其它常用的功能


### 3.4、初始化



RxHttpPlugins.init(OkHttpClient) //自定义OkHttpClient对象
.setDebug(boolean) //是否开启调试模式,开启后,logcat过滤RxHttp,即可看到整个请求流程日志
.setCache(File, long, CacheMode) //配置缓存目录,最大size及缓存模式
.setExcludeCacheKeys(String…) //设置一些key,不参与cacheKey的组拼
.setResultDecoder(Function) //设置数据解密/解码器,非必须
.setConverter(IConverter) //设置全局的转换器,非必须
.setOnParamAssembly(Function); //设置公共参数/请求头回调


此步骤是非必须的,如需要添加拦截器等其他业务需求,则可调用`init`方法进行初始化,不初始化或者传入`null`即代表使用默认OkHttpClient对象,建议在Application中初始化,默认的OkHttpClient对象在RxHttpPlugins类中可以找到,如下:



//Default OkHttpClient object in RxHttp
private static OkHttpClient getDefaultOkHttpClient() {
SSLParams sslParams = HttpsUtils.getSslSocketFactory();
return new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager)
.hostnameVerifier((hostname, session) -> true)
.build();
}


虽然初始化是非必须的,但是建议大家传入自定义的OkHttpClient对象,一来,自定义的OkHttpClient能最大化满足自身的业务;二来,随着RxHttp版本的升级,默认的OkHttpClient可能会发生变化(虽然可能性很小),故建议自定义OkHttpClient对象传入RxHttp。


### 3.5、公共参数/请求头


RxHttp支持为所有的请求添加公共参数/请求头,如下:



RxHttpPlugins
.init(okHttpClient)
.setOnParamAssembly(new Function() {
@Override
public Param apply(Param p) { //此方法在UI线程执行,请勿执行耗时操作
Method method = p.getMethod();
if (method.isGet()) { //可根据请求类型添加不同的参数
} else if (method.isPost()) {
}
return p.add(“versionName”, “1.0.0”)//添加公共参数
.addHeader(“deviceType”, “android”); //添加公共请求头
}
});


我们需要在`RxHttp`初始化的地方,通过`setOnParamAssembly`方法设置公共参数接口回调,此时每次发起请求,都会回调该接口。


当然,如果希望某个请求不回调该接口,即不添加公共参数/请求头,则可以调用`setAssemblyEnabled(boolean)`方法,并传入false即可,如下:



RxHttp.get(“/service/…”) //get请求
.setAssemblyEnabled(false) //设置是否添加公共参数/头部,默认为true
.asString() //返回字符串数据
.subscribe(s -> { //这里的s为String类型
//请求成功
}, throwable -> {
//请求失败
});


### 3.6、多域名/动态域名


**3.6.1、多域名**


现实开发中,我们经常会遇到多个域名的情况,其中1个为默认域名,其它为非默认域名,对于这种情况,RxHttp提供了`@DefaultDomain()`、`@Domain()`这两个注解来标明默认域名和非默认域名,如下:



public class Url {
@DefaultDomain() //设置为默认域名
public static String baseUrl = “https://www.wanandroid.com/”

@Domain(name = "BaseUrlBaidu") //非默认域名,并取别名为BaseUrlBaidu
public static String baidu = "https://www.baidu.com/";

@Domain(name = "BaseUrlGoogle") //非默认域名,并取别名为BaseUrlGoogle
public static String google = "https://www.google.com/";

}


通过`@Domain()`注解标注非默认域名,就会在RxHttp类中生成`setDomainToXxxIfAbsent()`方法,其中Xxx就是注解中取的别名。


上面我们使用了两个`@Domain()`注解,此时(需要Rebuild一下项目)就会在RxHttp类中生成`setDomainToBaseUrlBaiduIfAbsent()`、`setDomainToBaseUrlGoogleIfAbsent()`这两方法,此时发请求,我们就可以使用指定的域名,如下:



//使用默认域名,则无需添加任何额外代码
//此时 url = “https://www.wanandroid.com/service/…”
RxHttp.get(“/service/…”)
.asString()
.subscribe();

//手动输入域名,此时 url = “https://www.mi.com/service/…”
RxHttp.get(“https://www.mi.com/service/…”)
.asString()
.subscribe();

//手动输入域名时,若再次指定域名,则无效
//此时 url = “https://www.mi.com/service/…”
RxHttp.get(“https://www.mi.com/service/…”)
.setDomainToBaseUrlBaiduIfAbsent() //此时指定Baidu域名无效
.asString()
.subscribe();

//使用谷歌域名,此时 url = “https://www.google.com/service/…”
RxHttp.get(“/service/…”)
.setDomainToBaseUrlGoogleIfAbsent() //指定使用Google域名
.asString()
.subscribe();


通过以上案例,可以知道,RxHttp共有3种指定域名的方式,按优先级排名分别是:手动输入域名 > 指定非默认域名 > 使用默认域名。


**3.6.2、动态域名**


现实开发中,也会有动态域名切换的需求,如域名被封、或者需要根据服务端下发的域名去配置,这对于RxHttp来说简直就是 so easy !!! 我们只需要对BaseUrl重新赋值,此时发请求便会立即生效,如下:



//此时 url = “https://www.wanandroid.com/service/…”
RxHttp.get(“/service/…”)
.asString()
.subscribe();

Url.baseUrl = “https://www.qq.com”; //动态更改默认域名,改完立即生效,非默认域名同理
//此时 url = “https://www.qq.com/service/…”
RxHttp.get(“/service/…”)
.asString()
.subscribe();


### 3.7、关闭请求


我们知道,在Activity/Fragment中发起请求,如果页面销毁时,请求还未结束,就会有内存泄漏的危险,因此,我们需要在页面销毁时,关闭一些还未完成的请求,RxHttp提供了两种关闭请求的方式,分别是自动+手动。


**3.7.1、自动关闭请求**


自动关闭请求,需要引入本人开源的另一个库[RxLife]( ),先来看看如何用:



//以下代码均在FragmentActivty/Fragment中调用

RxHttp.postForm(“/service/…”)
.asString()
.as(RxLife.as(this)) //页面销毁、自动关闭请求
.subscribe();
//或者
RxHttp.postForm(“/service/…”)
.asString()
.as(RxLife.asOnMain(this)) //页面销毁、自动关闭请求 并且在主线程回调观察者
.subscribe();

//kotlin用户,请使用life或lifeOnMain方法,如下:
RxHttp.postForm(“/service/…”)
.asString()
.life(this) //页面销毁、自动关闭请求
.subscribe();
//或者
RxHttp.postForm(“/service/…”)
.asString()
.lifeOnMain(this) //页面销毁、自动关闭请求 并且在主线程回调观察者
.subscribe();


上面的`this`为`LifecycleOwner`接口对象,我们的FragmentActivity/Fragment均实现了这个接口,所有我们在FragmentActivity/Fragment中可以直接传`this`。 对`RxLife`不了解的同学请查看[RxLife 史上最优雅的管理RxJava生命周期]( ),这里不详细讲解。


**3.7.2、手动关闭请求**


手动关闭请求,我们只需要在订阅回调的时候拿到Disposable对象,通过该对象可以判断请求是否结束,如果没有,就可以关闭请求,如下:



//订阅回调,可以拿到Disposable对象
Disposable disposable = RxHttp.get(“/service/…”)
.asString()
.subscribe(s -> {
//成功回调
}, throwable -> {
//失败回调
});

if (!disposable.isDisposed()) { //判断请求有没有结束
disposable.dispose(); //没有结束,则关闭请求
}


### 3.8、文件上传/下载/进度监听


RxHttp可以非常优雅的实现上传/下载及进度的监听,是骡子是马,拉出来溜溜


**3.8.1上传**


通过addFile系列方法添加文件,如下:



RxHttp.postForm(“/service/…”) //发送Form表单形式的Post请求
.addFile(“file1”, new File(“xxx/1.png”)) //添加单个文件
.addFile(“fileList”, new ArrayList<>()) //通过List对象,添加多个文件
.asString()
.subscribe(s -> {
//上传成功
}, throwable -> {
//上传失败
});


通过upload系列方法监听上传进度,如下:



RxHttp.postForm(“/service/…”) //发送Form表单形式的Post请求
.addFile(“file1”, new File(“xxx/1.png”))
.addFiles(“file2”, new File(“xxx/2.png”))
.upload(AndroidSchedulers.mainThread(), progress -> {
//上传进度回调,0-100,仅在进度有更新时才会回调
int currentProgress = progress.getProgress(); //当前进度 0-100
long currentSize = progress.getCurrentSize(); //当前已上传的字节大小
long totalSize = progress.getTotalSize(); //要上传的总字节大小
})
.asString()
.subscribe(s -> {
//上传成功
}, throwable -> {
//上传失败
});


可以看到,跟上传的代码相比,我们仅仅增加了`upload`方法,第一个参数是指定回调的线程,这里我们指定了在UI线程中回调,第二个参数是进度监听回调,每当进度有更新时,都会回调该接口,


**3.8.2、下载**


下载使用`asDownload(String)`方法,传入本地路径即可



//文件存储路径
String destPath = getExternalCacheDir() + “/” + System.currentTimeMillis() + “.apk”;
RxHttp.get(“http://update.9158.com/miaolive/Miaolive.apk”)
.asDownload(destPath) //注意这里使用asDownload操作符,并传入本地路径
.subscribe(s -> {
//下载成功,回调文件下载路径
}, throwable -> {
//下载失败
});


如果你想监听下载进度,调用`asDownload(String, Scheduler, Consumer<Progress>)`方法,传入回调线程及回调接口即可,如下:



//文件存储路径
String destPath = getExternalCacheDir() + “/” + System.currentTimeMillis() + “.apk”;
RxHttp.get(“http://update.9158.com/miaolive/Miaolive.apk”)
.asDownload(destPath, AndroidSchedulers.mainThread(), progress -> { //第二个参数指定主线程回调
//下载进度回调,0-100,仅在进度有更新时才会回调,最多回调101次,最后一次回调文件存储路径
int currentProgress = progress.getProgress(); //当前进度 0-100
long currentSize = progress.getCurrentSize(); //当前已下载的字节大小
long totalSize = progress.getTotalSize(); //要下载的总字节大小
})
.subscribe(s -> {//s为String类型,这里为文件存储路径
//下载完成,处理相关逻辑
}, throwable -> {
//下载失败,处理相关逻辑
});


**3.8.3、断点下载**


`断点下载`相较于`下载`,仅需要调用`asAppendDownload`方法即可,其它没有任何差别



String destPath = getExternalCacheDir() + “/” + “test.apk”;
RxHttp.get(“http://update.9158.com/miaolive/Miaolive.apk”)
.asAppendDownload(destPath)
.subscribe(s -> { //s为String类型
//下载成功,处理相关逻辑
}, throwable -> {
//下载失败,处理相关逻辑
});


当然,此时你想监听下载进度,也是可以的,调用`asAppendDownload(String, Scheduler, Consumer<Progress>)`方法,传入回调线程及回调接口即可,如下:



String destPath = getExternalCacheDir() + “/” + “test.apk”;
RxHttp.get(“http://update.9158.com/miaolive/Miaolive.apk”)
.asAppendDownload(destPath, AndroidSchedulers.mainThread(), progress -> {
//下载进度回调,0-100,仅在进度有更新时才会回调
int currentProgress = progress.getProgress(); //当前进度 0-100
long currentSize = progress.getCurrentSize(); //当前已下载的字节大小
long totalSize = progress.getTotalSize(); //要下载的总字节大小
}) //指定主线程回调
.subscribe(s -> { //s为String类型
//下载成功,处理相关逻辑
}, throwable -> {
//下载失败,处理相关逻辑
});


### 3.9、超时设置


**3.9.1、设置全局超时**


RxHttp内部默认的读、写、连接超时时间均为10s,如需修改,请自定义OkHttpClient对象,如下:



//设置读、写、连接超时时间为15s
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(15, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.build();
RxHttp.init(client);


**3.9.2、为单个请求设置超时**


为单个请求设置超时,使用的是RxJava的`timeout(long timeout, TimeUnit timeUnit)`方法,如下:



RxHttp.get(“/service/…”)
.asString()
.timeout(5, TimeUnit.SECONDS)//设置总超时时间为5s
.as(RxLife.asOnMain(this)) //感知生命周期,并在主线程回调
.subscribe(s -> {
//成功回调
}, (OnError) error -> {
//失败回调
});


**注:这里设置的总超时时间要小于全局读、写、连接超时时间之和,否则无效**


### 3.10、设置Converter


**3.10.1、设置全局Converter**



IConverter converter = FastJsonConverter.create();
RxHttpPlugins.init(OkHttpClient)
.setConverter(converter)


**3.10.2、为请求设置单独的Converter**


首先需要在任意public类中通过@Converter注解声明Converter,如下:



public class RxHttpManager {
@Converter(name = “XmlConverter”) //指定Converter名称
public static IConverter xmlConverter = XmlConverter.create();
}


然后,rebuild 一下项目,就在自动在RxHttp类中生成`setXmlConverter()`方法,随后就可以调用此方法为单个请求指定Converter,如下:



RxHttp.get(“/service/…”)
.setXmlConverter() //指定使用XmlConverter,不指定,则使用全局的Converter
.asClass(NewsDataXml.class)
.as(RxLife.asOnMain(this)) //感知生命周期,并在主线程回调
.subscribe(dataXml -> {
//成功回调
}, (OnError) error -> {
//失败回调
});


### 3.11、请求加解密


**3.11.1、加密**


请求加密,需要自定义Param,非常简单,详情请查看本文5.2章节----自定义Param


**3.11.2、解密**


有些时候,请求会返回一大串的密文,此时就需要将密文转化为明文,直接来看代码,如下:



//设置数据解密/解码器
RxHttpPlugins.init(OkHttpClient)
.setResultDecoder(new Function<String, String>() {
//每次请求成功,都会回调这里,并传入请求返回的密文
@Override
public String apply(String s) throws Exception {
String plaintext = decode(s); //将密文解密成明文,解密逻辑自己实现
return plaintext; //返回明文
}
});


很简单,通过`RxHttp.setResultDecoder(Function<String, String>)`静态方法,传入一个接口对象,此接口会在每次请求成功的时候被回调,并传入请求返回的密文,只需要将密文解密后返回即可。


然而,有些请求是不需求解密的,此时就可以调用`setDecoderEnabled(boolean)`方法,并传入false即可,如下:



RxHttp.get(“/service/…”)
.setDecoderEnabled(false) //设置本次请求不需要解密,默认为true
.asString()
.subscribe(s -> {
//成功回调
}, (OnError) error -> {
//失败回调
});


### 3.12、同步请求/指定回调线程


RxHttp默认在Io线程执行请求,也默认在Io线程回调,即默认在同一Io线程执行请求并回调,当然,我们也可以指定请求/回调所在线程。


**3.12.1、同步请求**


RxHttp默认在IO线程发起请求,即异步请求,如果需要同步请求,调用`setSync`方法即可,如下:



//指定请求所在线程,需要在第二部曲前任意位置调用,第二部曲后调用无效
RxHttp.get(“/service/…”)
.setSync() //同步执行,
.asString()
.subscribe();


以上使用的皆是RxJava的线程调度器,不熟悉的请自行查阅相关资料,这里不做详细介绍。




![img](https://img-blog.csdnimg.cn/img_convert/e07c523ebb36b75b9945fc4950959ddc.png)
![img](https://img-blog.csdnimg.cn/img_convert/c2f7db0a09915f4dd0a935c535e8c30e.png)

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618636735)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

回即可。


然而,有些请求是不需求解密的,此时就可以调用`setDecoderEnabled(boolean)`方法,并传入false即可,如下:



RxHttp.get(“/service/…”)
.setDecoderEnabled(false) //设置本次请求不需要解密,默认为true
.asString()
.subscribe(s -> {
//成功回调
}, (OnError) error -> {
//失败回调
});


### 3.12、同步请求/指定回调线程


RxHttp默认在Io线程执行请求,也默认在Io线程回调,即默认在同一Io线程执行请求并回调,当然,我们也可以指定请求/回调所在线程。


**3.12.1、同步请求**


RxHttp默认在IO线程发起请求,即异步请求,如果需要同步请求,调用`setSync`方法即可,如下:



//指定请求所在线程,需要在第二部曲前任意位置调用,第二部曲后调用无效
RxHttp.get(“/service/…”)
.setSync() //同步执行,
.asString()
.subscribe();


以上使用的皆是RxJava的线程调度器,不熟悉的请自行查阅相关资料,这里不做详细介绍。




[外链图片转存中...(img-H5IxQxJi-1715617022836)]
[外链图片转存中...(img-an9dE3Hs-1715617022837)]

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618636735)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

  • 26
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值