写点什么

可怕!RxHttp2,95%Android 开发者已收藏的十大开源库

用户头像
Android架构
关注
发布于: 刚刚

//同时获取两个学生信息


suspend void initData() {


val asyncStudent1 = RxHttp.postForm("/service/...")


.toClass<Student>()


.async() //这里会返回 Deferred<Student>


val asyncStudent2 = RxHttp.postForm("/service/...")


.toClass<Student>()


.async() //这里会返回 Deferred<Student>


//随后调用 await 方法获取对象


val student1 = asyncStudent1.await()


val student2 = asyncStudent2.await()


}


3.4、delay、startDelay 延迟




delay操作符是请求结束后,延迟一段时间返回;而startDelay操作符则是延迟一段时间后再发送请求,如下:


val student = RxHttp.postForm("/service/...")


.toClass<Student>()


.delay(1000) //请求回来后,延迟 1s 返回


.await()


val student = RxHttp.postForm("/service/...")


.toClass<Student>()


.startDelay(1000) //延迟 1s 后再发送请求


.await()


3.5、onErrorReturn、onErrorReturnItem 异常默认值




有些情况,我们不希望请求出现异常时,直接走异常回调,此时我们就可以通过两个操作符,给出默认的值,如下:


//根据异常给出默认值


val student = RxHttp.postForm("/service/...")


.toClass<Student>()


.timeout(100) //超时时长为 100 毫秒


.onErrorReturn {


//如果时超时异常,就给出默认值,否则,抛出原异常


return@onErrorReturn if (it is TimeoutCancellationException)


Student()


else


throw it


}


.await()


//只要出现异常,就返回默认值


val student = RxHttp.postForm("/service/...")


.toClass<Student>()


.timeout(100) //超时时长为 100 毫秒


.onErrorReturnItem(Student())


.await()


3.6、tryAwait 异常返回 null




如果你不想在异常时返回默认值,又不想异常是影响程序的执行,tryAwait就派上用场了,它会在异常出现时,返回 null,如下:


val student = RxHttp.postForm("/service/...")


.toClass<Student>()


.timeout(100) //超时时长为 100 毫秒


.tryAwait() //这里返回 Student? 对象,即有可能为空


3.7、map 转换符号




map操作符很好理解,RxJava 即协程的 Flow 都有该操作符,功能都是一样,用于转换对象,如下:


val student = RxHttp.postForm("/service/...")


.toStr()


.map { it.length } //String 转 Int


.tryAwait() //这里返回 Student? 对象,即有可能为空


3.8、以上操作符随意搭配




以上操作符,可随意搭配使用,但调用顺序的不同,产生的效果也不一样,这里悄悄告诉大家,以上操作符只会对上游代码产生影响。


timeout及retry


val student = RxHttp.postForm("/service/...")


.toClass<Student>()


.timeout(50)


.retry(2, 1000) { it is TimeoutCancellationException }


.await()


以上代码,只要出现超时,就会重试,并且最多重试两次。


但如果timeoutretry互换下位置,就不一样了,如下:


val student = RxHttp.postForm("/service/...")


.toClass<Student>()


.retry(2, 1000) { it is TimeoutCancellationException }


.timeout(50)


.await()


此时,如果 50 毫秒内请求没有完成,就会触发超时异常,并且直接走异常回调,不会重试。为什么会这样?原因很简单,timeout及retry操作符,仅对上游代码生效。如 retry 操作符,下游的异常是捕获不到的,这就是为什么 timeout 在 retry 下,超时时,重试机制没有触发的原因。


在看timeoutstartDelay操作符


val student = RxHttp.postForm("/service/...")


.toClass<Student>()


.startDelay(2000)


.timeout(1000)


.await()


以上代码,必定会触发超时异常,因为 startDelay,延迟了 2000 毫秒,而超时时长只有 1000 毫秒,所以必定触发超时。 但互换下位置,又不一样了,如下:


val student = RxHttp.postForm("/service/...")


.toClass<Student>()


.timeout(1000)


.startDelay(2000)


.await()


以上代码正常情况下,都能正确拿到返回值,为什么?原因很简单,上面说过,操作符只会对上游产生影响,下游的startDelay延迟,它是不管的,也管不到。


4、协程开启/关闭/异常处理


=========================================================================


在以上示例中,我们统一用到await/tryAwait操作符获取请求返回值,它们都是suspend挂起函数,需要在另一个suspend挂起函数或者协程中才能被调用,故我们提供了RxLifeScope库来处理协程开启、关闭及异常处理,用法如下:


在 FragemntActivity/Fragment/ViewModel 环境下


在该环境下,直接调用rxLifeScope对象的lanuch方法开启协程即可,如下:


rxLifeScope.lanuch({


//协程代码块,运行在 UI 线程


val student = RxHttp.postForm("/service/...")


.toClass<Student>()


.await()


//可直接更新 UI


}, {


//异常回调,这里可以拿到 Throwable 对象


})


以上代码,会在页面销毁时,自动关闭协程,同时自动关闭请求,无需担心内存泄露问题


非 FragemntActivity/Fragment/ViewModel 环境下


该环境下,我们需要手动创建RxLifeScope对象,随后调用lanuch方法开启协程


val job = RxLifeScope().lanuch({


//协程代码块,运行在 UI 线程


val student = RxHttp.postForm("/service/...")


.toClass<Student>()


.await()


//可直接更新 UI


}, {


//异常回调,这里可以拿到 Throwable 对象


})


//在合适的时机关闭协程


job.cancel()


以上代码,由于未与生命周期绑定,故我们需要在合适的时机,手动关闭协程,协程关闭,请求也会跟着关闭


监听协程开启/结束回调


以上我们在lanuch方法,传入协程运行回调及异常回调,我们也可以传入协程开启及结束回调,如下:


rxLifeScope.launch({


//协程代码块


val student = RxHttp.postForm("/service/...")


.toClass<Student>()


.await()


//可直接更新 UI


}, {


//异常回调,这里可以拿到 Throwable 对象,运行在 UI 线程


}, {


//开始回调,可以开启等待弹窗,运行在 UI 线程


}, {


//结束回调,可以销毁等待弹窗,运行在 UI 线程


})

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
可怕!RxHttp2,95%Android开发者已收藏的十大开源库