Как использовать переменную Object Observable внутри другой функции подписки Observable – RxJava

У меня есть две наблюдаемые разных типов, которые испускают два разных типа объектов. Но мне нужно обновить аналитику при успешном входе в систему с идентификатором пользователя и ролью. Идентификатор пользователя уже установлен в вызове функции входа в систему viewModel при успешном входе в систему.

                       viewModel.login(emailId)
                                .observeOn(AndroidSchedulers.mainThread())
                                .autoDisposable(scopeProvider)
                                .subscribe({ (role, images) ->
                                analyticsProvider.updateUser(mapOf(Constants.Role to role, 
Constants.userId to *NEED TO ENTER USER ID FROM OTHER OBSERVABLE HERE*)))

My Session Observable, который испускает объект пользователя.

 class SessionClass{
        private val user = BehaviorSubject.create<User>()
        override fun setUser(user: User) {
                this.user.onNext(user)
            }
         override fun getUser(): Observable<User> = user.hide()
    }

Я пытался вызвать SessionClass().getUser().blockingFirst().userId в этом месте, но телефон зависает на экране входа в систему.

Можно ли как-то решить эту проблему?

0
0
460
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваше решение не работает просто потому, что вы немедленно создаете экземпляр SessionClass и никогда не вызываете setUser(), поэтому getUser().blockingFirst() заблокируется навсегда. Я предполагаю, что у вас есть экземпляр SessionClass, который на самом деле будет вызывать setUser() в какой-то момент.

Ключом к доступу к пользователю является комбинировать Observables. Подходящим выбором в этой ситуации является оператор zipWith. Это позволит вам оперировать значениями из двух источников одновременно. Например, ваш код может выглядеть примерно так:

val session: SessionClass = TODO() // get an instance somewhere

viewModel.login(emailId)
    .observeOn(AndroidSchedulers.mainThread())
    .zipWith(session.getUser().firstOrError(), BiFunction { (role, images): Pair<Role, Images>, user: User -> Triple(role, images, user) })
    .autoDisposable(scopeProvider)
    .subscribe({ (role, images, user) ->
        analyticsProvider.updateUser(mapOf(Constants.Role to role, Constants.userId to user.userId))
    })))

Спасибо Панда. Попробую. Но у меня есть сомнения. Я использовал немного другой подход. Я использовал оператор zip и создал функцию Bi, которая возвращает экземпляр созданного мной пользовательского объекта, содержащего все поля. Есть ли причина, по которой zipWith выбран, а не zip?

ASN 29.05.2019 03:51

А еще zipWith не распознается после autoDisposable :(

ASN 29.05.2019 03:59

@ASN a.zipWith(b, zipper) похож на Observable.zip(a, b, zipper), за исключением того, что вы можете связать его, чтобы он выглядел лучше. После вызова autoDisposable вы можете только subscribe. Я обновил свой ответ, чтобы отразить это.

Panda 29.05.2019 04:53

видимо viewModel.sessionManager().blockingGet().getUser() это Observable<User>. Но zipWith ожидает Single вместо Observable

ASN 29.05.2019 05:14

Вы можете использовать один из операторов first, чтобы преобразовать его в Single.

Panda 29.05.2019 05:26

Но в этом случае что мне нужно передать как значение по умолчанию оператору first.

ASN 29.05.2019 08:33

Другие вопросы по теме

Похожие вопросы