跳至主要內容

使用响应式编程进行后台工作

guodongAndroid大约 2 分钟

使用响应式编程进行后台工作

基于回调的方法最重要的问题是将数据从一个函数传递到另一个函数。这将导致难以阅读和维护的嵌套回调。

回想一下队列和管道,它们操作数据流,你可以其上随时监听数据。响应式框架,例如 Rx(或响应式扩展)或 Kotlin Flows,是建立在将异步操作封装在事件流中的想法之上的。使用这些框架的编程称为响应式编程,其中每个操作符和流都会对之前的操作符做出响应。

响应式编程使用观察者模式。此外,还有大量的操作符可以扩展可观察流的行为,从而实现清晰和富有表现力的数据处理方式。 你可以使用单个 lambda 函数以多种方式订阅事件流,map 、fliter、reduce 和 combine ,以及处理整个操作链中的错误。

前面加载、调整和上传图片大小的示例,使用 Rx 重写的话,类似如下代码:

fun uploadImage(imagePath: String) {
    loadImage(imagePath)
    	.doOnSubscribe(::showLoadingSpinner)
    	.flatMap(::resizeImage)
	    .flatMapCompletable(::uploadImage)
    	.subscribe(::hideLoadingSpinner, ::handleError)
}

起初,这段代码看起来可能比较奇怪。实际上,它是使用一串运算符修改的数据流。它从 flatMap 运算符开始,该运算符获取一些数据(来自 loadImage 的图像)并将其传递给另一个函数,从而创建一个新的数据流。然后,新的数据流使用 flatMapCompletable 操作符组成的操作符链,将从 resizedImage 函数发送的数据传递给 uploadImage 函数。最后,uploadImage 函数不传递数据,而是传递完成事件,它通知你在上传完成时隐藏进度条。

这些数据和操作符在有人使用 subscribe(onComplete, onError) 订阅它们之前实际上不会被执行。

此外,doOnSubscribe 会在订阅流是被执行。还有像 doOnSuccess 和 doOnError 这样的函数,它们响应各自的事件。

此外,更重要的是,在操作符链中的任何操作发生的任何错误或异常不会被抛出,并且应用程序不会崩溃。相反,数据流将继续向下传递,最终到达 onError lambda。而回调是不具备这种行为的;它们只会抛出异常,你必须自己使用 try/catch 块处理异常。

在异步编程方面,响应式扩展比回调更简洁,但它们也有更陡峭的学习曲线。

有大量的操作符,不同类型的流,以及在线程之间切换时有很多需要注意的情况,要完全理解它们需要大量的时间。

在下一节中,我们讨论响应式编程的学习曲线和其他一些问题。