尽管使用RxJava

时间:2017-08-24 02:15:40

标签: java android multithreading kotlin rx-java

注意:我使用Kotlin和RxKotlin作为有用的扩展功能。

我尝试使用Google的People API获取一些用户数据,而我只是将我的所有AsyncTasks和东西迁移到使用RxJava。除了这一部分,一切正常:

private fun getGooglePerson(service: PeopleService?, account: GoogleSignInAccount) =
    Single.just(service?.people()
                    ?.get("people/me")
                    ?.setPersonFields("emailAddresses,birthdays,genders,phoneNumbers")
                    ?.execute() ?: Person()) // If null, return an empty person (shouldn't ever be null, though)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeBy(
                    onError = {/*Do something*/},
                    onSuccess = {/*Do something*/}
            )

具体来说,我收到IllegalStateException消息Calling this from your main thread can lead to deadlock。我很困惑,因为我认为调用subscribeOn应该将其上方和下方的所有内容(除非observeOn跟随它)转移到另一个线程(在这种情况下,{{1}我尝试重写代码如下:

Schedulers.io()

仍然没有骰子。我完全难过了;我该怎么办?我应该在哪里调用private fun getGooglePerson(service: PeopleService?, account: GoogleSignInAccount) = service?.people() ?.get("people/me") ?.setPersonFields("emailAddresses,birthdays,genders,phoneNumbers") ?.execute() ?: Person() // If null, return an empty person (shouldn't ever be null, though) .toSingle() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeBy( onError = {/*Do something*/}, onSuccess = {/*Do something*/} ) 以便它在不同的线程上运行?我错过了什么吗?

1 个答案:

答案 0 :(得分:0)

让我们稍微分解一下。

Single.just(service?.people()
                    ?.get("people/me")
                    ?.setPersonFields("emailAddresses,birthdays,genders,phoneNumbers")
                    ?.execute() ?: Person())
            .subscribeOn(Schedulers.io())

我们从Single.just(someValue)开始。我们可以像这样重写你的代码,它在技术上与你所写的相同:

val person = service?.people()
                    ?.get("people/me")
                    ?.setPersonFields("emailAddresses,birthdays,genders,phoneNumbers")
                    ?.execute() ?: Person())
Single.just(person)

你看到了问题吗?首先执行服务调用,以便为Single.just调用提供值。

为了在设置链的其余部分后(即订阅时)运行服务调用,您可以使用defer

Single.defer(() -> service?.people()
                    ?.get("people/me")
                    ?.setPersonFields("emailAddresses,birthdays,genders,phoneNumbers")
                    ?.execute() ?: Person())
            .subscribeOn(Schedulers.io())

(语法可能已关闭,我没有IDE方便)