Есть ли способ поделиться наблюдаемым оператором RxSwift, например, просто, из, et c? - PullRequest
0 голосов
/ 20 апреля 2020

Я пытаюсь поделиться результатом сопоставления наблюдаемых, созданных оператором just().

let observable = Observable.just(())
  .map { _ -> String in
    print("block is called")
    return "some transformation"
  }
  .share()

observable
  .subscribe()
  .disposed(by: disposeBag)

observable
  .subscribe()
  .disposed(by: disposeBag)

Но код выдает результат дважды:

block is called
block is called

Я хочу map() будет вызван только один раз, поэтому я подумал, что share() будет достаточно. Есть ли способ поделиться результатом, полученным из примера кода?

1 Ответ

2 голосов
/ 20 апреля 2020

Краткий ответ:
Просто используйте .forever область видимости следующим образом: .share(scope: .forever)

Длинный ответ:
Значение по умолчанию для области: .whileConnected. Это означает, что эта наблюдаемая будет иметь общие значения, пока кто-то подписан. Давайте посмотрим, так ли это в вашем случае. Вы можете добавить дополнительное ведение журнала следующим образом:

let observable = Observable.just(())
    .map { _ -> String in
        print("block is called")
        return "some transformation"
      }
    .share()
    .debug("Debug") // Change is here

    observable
      .subscribe()
      .disposed(by: disposeBag)

    observable
      .subscribe()
      .disposed(by: disposeBag)

Результат журнала равен

2020-04-20 08:18:46.947: Debug -> subscribed
block is called
2020-04-20 08:18:46.954: Debug -> Event next(some transformation)
2020-04-20 08:18:46.954: Debug -> Event completed
2020-04-20 08:18:46.955: Debug -> isDisposed
2020-04-20 08:18:46.955: Debug -> subscribed
block is called
2020-04-20 08:18:46.956: Debug -> Event next(some transformation)
2020-04-20 08:18:46.956: Debug -> Event completed
2020-04-20 08:18:46.956: Debug -> isDisposed

Таким образом, вы можете видеть, что ваша первая подписка заканчивается сразу после .subscribe() вызов, поэтому наблюдаемое не разделяет значение

Это происходит потому, что по умолчанию подписка и наблюдение выполняются в непосредственном планировщике, прямо в потоке, в котором создается наблюдаемое. Так что на самом деле этот код является синхронным!

В этом случае вы можете либо изменить область общего ресурса на .forever, либо просто наблюдать асинхронно в каком-то другом потоке, в этом случае MainScheduler.asyncInstance выполнит эту работу.

Также хочу заметить, что у функции share есть еще один параметр - количество повторов, по умолчанию равное 0. Это означает, что он поделится всеми событиями, созданными наблюдаемой. С длинными последовательностями это может вызвать высокое использование памяти, и это то, на что вам следует обратить внимание. Чтобы предотвратить OOM, вы можете установить количество 1

share(replay: 1, scope: .forever)
...