ios - 在创建 Observable/Single 时获取传递给 subscribeOn() 的调度程序
问题描述
让我展示一个我正在努力解决的问题的简化示例:
class CarService {
func getCars() -> Single<[Car]> {
return Single.create { observer in
// Here we're using a thread that was defined in subscribeOn().
someCallbackToAPI { cars in
// Here we're using main thread, because of the someCallbackToAPI implementation.
observer(.success(cars))
}
}
}
}
class CarRepository {
func syncCars() -> Completable {
return CarService().getCars()
.flatMapCompletable { cars in
// Here we're using main thread, but we want some background thread.
saveCars(cars)
}
}
}
class CarViewController {
func loadCar() {
CarRepository().syncCars()
.subscribeOn(someBackgroundScheduler)
.observeOn(MainThread)
.subscribe()
}
}
从底部:CarViewController
想要从一些外部 API 同步所有汽车。它定义了应该使用哪个线程进行同步subscribeOn
——我们不想阻塞 UI 线程。不幸的是,在下面,CarService
必须使用一些外部库方法(someCallbackToAPI
),这些方法总是在主线程中返回结果。问题是在收到结果后,下面的所有方法,例如,saveCars
都在同一个主线程中调用。saveCars
可能会阻塞 UI 线程,因为它将数据保存到数据库。当然,我可以在 和 之间的线程之间添加,observeOn
但我希望转储并且对线程一无所知。定义工作线程是责任。CarService().getCars()
flatMapCompletable
CarRepository
CarViewController
所以我的问题是,我是否可以让调度程序传入subscribeOn
方法并在收到结果后切换回调度程序someCallbackToApi
?
解决方案
最简洁的答案是不。
正如您推测的那样,问题在于您someCallbackToAPI
正在路由到主线程,这不是您想要的,并且除了重新编写 someCallbackToAPI 之外,您无能为力。如果您使用的是 Alamofire 或 Moya,我认为他们有替代方法不会在主线程上调用闭包,但我不确定。URLSession 不会切换到主线程,因此一个想法是改用它。
如果您希望在saveCars
后台线程上发生,则必须使用 observeOn 将计算从 main 推回后台线程。唯一subscribeOn
要做的就是在后台线程上调用 someCallbackToAPI(_:)
,它不能指定函数将在哪个线程上调用其闭包。
所以像:
func syncCars() -> Completable {
return CarService().getCars()
.observeOn(someBackgroundScheduler)
.flatMapCompletable { cars in
// Now this will be on the background thread.
saveCars(cars)
}
}
最后一点,空订阅是一种代码异味。任何时候你发现自己要求.subscribe()
测试目的以外的任何事情,你都可能做错了什么。
推荐阅读
- oracle - 使用 Kafka Connect API JDBC Sink 连接器示例到 Oracle 数据库的 Kafka 主题
- android - 如何将 Android 日志条目存储为字符串
- javascript - 通过 jQuery 检索并显示特定值
- c++ - 在 bazel 中创建仅系统标头库的正确方法是什么?
- python - 如何让用户通过 Python 中的命令行指定枚举
- r - 从不规则间距 x 和 y 的 ncdf 创建光栅砖
- xcode - 如何在 Xcode 10 中设置观察点?
- python - 尝试在 Windows 10 上安装库“pycld2”时收到错误
- python - 设置类变量
- reactjs - 反应路由器参数-Apache服务器上的页面刷新失败