我遇到很多用户抱怨他们的应用程序冻结,我怀疑这是由于网络请求。
很难重现,但我的解决方案是在我的自定义 mapArray 函数中添加 subscribeOn 和 observeOn,该函数链接在 moya 请求之后但在任何 ui 使用之前。
问题:
- 这种调用 subscribeOn 和 observeOn 的顺序作为解决冻结问题的方法是否有意义?
- 在调用函数之后调用 subscribeOn 感觉很奇怪,但我不想将我的请求包装在另一个调度块中
总的来说,我对 Moya 和 Alamofire 中的线程切换感到很困惑,希望有人能发光:
PS:我已经阅读了moya中讨论这个的问题,它提到alamofire在主线程上进行网络调用,这也让我感到困惑
PS2:这个解决方案也是基于这篇博文,但我的问题是,除了上述问题之外,为什么它可能提倡在后台线程上运行网络调用,而对于 Moya 家伙来说似乎并非如此。
// How the network call is
func load() -> Observable<Void> {
let apiProvider: RxMoyaProvider()
return apiProvider.request(.GetFeed(page: 1))
.mapArray(Question.self, keyPath: "questions")
.doOnNext { questions, pagination in
// updates the results to a variable, which is bound to the UI
self.pagination = pagination
self.data.value = questions
}
.flatMapLatest { _ in
Observable.just()
}
}
// My observable extension, a function to map responses to a
extension ObservableType where E == Response {
func mapObject<T: Mappable>(type: T.Type, keyPath: String) -> Observable<T> {
return
// this makes sure that the beginning of the call is made on the background thread. but it can be changed later, so we need an observe on later on
subscribeOn(ConcurrentDispatchQueueScheduler(globalConcurrentQueueQOS: .Background))
.doOnError(networkFailureCallback)
.filterSuccessfulStatusCodes()
.handleUnauthorizedRequest()
// this makes sure that the mapping happens on a background thread as well
.observeOn(ConcurrentDispatchQueueScheduler(globalConcurrentQueueQOS: .Background))
.flatMap { response -> Observable<T> in
return Observable.just(try response.mapObject(T.self, keyPath: keyPath))
}
}
}
// In my viewController
dataAccessor.load()
.observeOn(MainScheduler.instance)
.subscribe { error in
// do actions
}
.addDisposableTo(self.disposeBag)