Как выполнить RxSwift в фоновом режиме?

#multithreading #concurrency #grand-central-dispatch #rx-swift

#многопоточность #параллелизм #grand-central-dispatch #rx-быстрый

Вопрос:

Я пытаюсь выполнить сложное вычисление в фоновом режиме при выборе строки таблицы, но это замораживает пользовательский интерфейс. Пожалуйста, взгляните на мой код и скажите мне, что может быть не так.

 tableView.rx
    .modelSelected(Sring.self)
    .flatMap { item -> Observable<String> in
        
        for _ in 1...2_500 {
            for _ in 1...1_000 {
                
            }
        }
        return Observable.just("Hello world!")

    }
    .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .background))
    .observeOn(MainScheduler.instance)
    .retry()
    .subscribe(onNext: { value in
        print(value)
    })
    .disposed(by: bag)
 

Ответ №1:

Первое, что нужно понять с помощью этого кода, — это то, что subscribeOn определяет, в каком потоке будет вызываться генератор событий наблюдаемого, а не в каком потоке будут передаваться значения. Если исходный наблюдаемый объект генерируется в том же потоке, на который он подписан, тогда ваш код сработал бы (например, если бы вы использовали Observable.just(_:) . Но modelSelected генерируется в основном потоке, независимо от того, на какой поток он был подписан. flatMap Оператор вызывает свое закрытие в потоке, в котором испускается его источник, так что он также находится в основном потоке.

Результатом всего этого является то , что звонить редко бывает полезно subscribeOn(_:) . Единственный раз, когда он действительно делает то, что вы ожидаете, — это если конечный источник (самый восходящий) Наблюдаемого генератора является синхронной блокирующей функцией. (Чего нельзя сказать о случае с tableView.rx.modelSelected(String.self) )

То, что вы хотите в данном случае, — это нечто большее, чем:

 tableView.rx.modelSelected(String.self)
    .observeOn(ConcurrentDispatchQueueScheduler(qos: .background))
    .flatMap { item -> Observable<String> in
        sleep(3)
        return Observable.just("Hello world!")
    }
    .retry()
    .observeOn(MainScheduler.instance)
    .subscribe(onNext: { value in
        print(value)
    })
    .disposed(by: bag)
 

Комментарии:

1. Большое вам спасибо за ваше любезное объяснение. Все работает так же, как в вашем коде выше.