例外:尽管我在另一个线程上存在,但不能在UI线程上调用blockingConnect

时间:2017-10-23 10:17:00

标签: multithreading kotlin rx-java rx-java2

我有这样的调用:

 val connectionResult = googleApiClient.blockingConnect()

是造成此例外的原因:

  

java.lang.IllegalStateException:不得在UI线程上调用blockingConnect

at com.google.android.gms.common.internal.zzbp.zza(Unknown Source)
at com.google.android.gms.common.api.internal.zzbd.blockingConnect(Unknown Source)
at com.elstatgroup.elstat.NexoLocationManager.startLocationUpdatesGmsApi(NexoLocationManager.kt:510)
at com.elstatgroup.elstat.NexoLocationManager.startLocationUpdates(NexoLocationManager.kt:498)
at com.elstatgroup.elstat.NexoLocationManager.appendRSSIEvent(NexoLocationManager.kt:283)
at com.elstatgroup.elstat.NexoLocationManager.appendRSSIEvent(NexoLocationManager.kt:273)
at com.elstatgroup.elstat.NexoLocationTest.testAppendLocationEvents(NexoLocationTest.kt:111)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.robolectric.RobolectricTestRunner$HelperTestRunner$1.evaluate(RobolectricTestRunner.java:497)
at org.robolectric.internal.SandboxTestRunner$2.evaluate(SandboxTestRunner.java:228)
at org.robolectric.internal.SandboxTestRunner.runChild(SandboxTestRunner.java:110)
at org.robolectric.internal.SandboxTestRunner.runChild(SandboxTestRunner.java:37)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.robolectric.internal.SandboxTestRunner$1.evaluate(SandboxTestRunner.java:64)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

我想,这会有所帮助:

 Observable.just(googleApiClient.blockingConnect())
                    .subscribeOn(Schedulers.newThread())
                    .subscribe(Consumer { connectionResult ->
                        if (connectionResult.isSuccess()) {

                //do something
                     }
                    })

但我错了,这没有用。 我让它不崩溃的唯一方法是:

         Thread(Runnable {
                val connectionResult = googleApiClient.blockingConnect() 
                if (connectionResult.isSuccess()) {
                    //do something
                }
            }).start()

那么为什么我的RxJava解决方案不起作用?

2 个答案:

答案 0 :(得分:1)

这是因为Observable#只是渴望并且会阻止直到#blockingConnect结束。

这个例子可以解决这个问题:

    Observable.fromCallable(() -> {
        return googleApiClient.blockingConnect();
    }).subscribeOn(Schedulers.io());

答案 1 :(得分:1)

Observable.just()接受传递给下一个链接的observable的值。如果你仔细检查,那么在你的情况下

Observable.just(googleApiClient.blockingConnect())
首先执行

googleApiClient.blockingConnect(),因为just运算符需要值/值。所以你需要一个接受函数调用的操作符。

对于您的案例,可以使用Observable.fromCallable()接收可调用的参数:

Observable.fromCallable(() -> googleApiClient.blockingConnect());

当您订阅可观察链时,googleApiClient.blockingConnect()将执行。