多くのユーザーがアプリのフリーズについて不平を言っていますが、それはネットワーク リクエストが原因であると思われます。
再現するのは大変でしたが、私の解決策は、カスタム mapArray 関数に subscribeOn と observeOn を追加することでした。これは、moya リクエストの後、UI の使用前にチェーンされます。
質問:
- フリーズの問題を解決するためのアプローチとして、subscribeOn とobserveOn を呼び出すこのシーケンスは理にかなっていますか?
- 呼び出す関数の後にsubscribeOn を呼び出すのは奇妙に感じますが、リクエストをさらに別のディスパッチ ブロックでラップしたくありません。
全体として、私は Moya と Alamofire でのスレッドの切り替えにかなり混乱しており、誰かが光を当ててくれることを願っています:
PS: moya でこれについて議論している問題を読んだところ、 alamofire がメイン スレッドでネットワーク呼び出しを行うことが言及されていますが、これも混乱を招きます。
PS2: このソリューションもこのブログ投稿に基づいていますが、私の質問は、上記の質問に加えて、ネットワーク呼び出しをバックグラウンド スレッドで実行することを提唱するのはなぜかということです。
// 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)