Android RxJava调用在I';已设置订阅(Schedulers.io())
根据我对RxJava的理解,Android RxJava调用在I';已设置订阅(Schedulers.io()),android,rx-java2,Android,Rx Java2,根据我对RxJava的理解,sendMessage()必须在后台io线程上执行,其结果可以在Android主线程上看到。然而,sendMessage()方法似乎无论如何都是在Android主线程上运行的,我的应用程序崩溃了(我在catch(e:Exception)中捕捉到它),原因是Android.os.NetworkOnMainThreadException 这是我的代码: import androidx.lifecycle.ViewModel import com.company.oplog
sendMessage()
必须在后台io线程上执行,其结果可以在Android主线程上看到。然而,sendMessage()
方法似乎无论如何都是在Android主线程上运行的,我的应用程序崩溃了(我在catch(e:Exception)
中捕捉到它),原因是Android.os.NetworkOnMainThreadException
这是我的代码:
import androidx.lifecycle.ViewModel
import com.company.oplogger.Logger
import com.company.optikbtv.utility.applySingleAsync
import com.company.optikbtv.utility.defaultErrorFun
import com.uber.autodispose.android.lifecycle.AndroidLifecycleScopeProvider
import com.uber.autodispose.lifecycle.autoDisposable
import io.reactivex.Single
import org.koin.core.parameter.parametersOf
import org.koin.standalone.KoinComponent
import org.koin.standalone.inject
import java.io.IOException
import java.net.*
const val UDP_HOST = "10.0.2.2" // Localhost
const val UDP_PORT = 3042
class EASViewModel : ViewModel(), KoinComponent {
private val logger: Logger by inject { parametersOf(this) }
private lateinit var scopeProvider: AndroidLifecycleScopeProvider
private val socket = DatagramSocket()
fun startEAS() {
sendMessage(socket, UDP_HOST, UDP_PORT)
.compose(applySingleAsync())
.doOnDispose { logger.d("Disposing subscription from the EASViewModel.startEAS()") }
.autoDisposable(scopeProvider)
.subscribe({
logger.d("on Subscribe: $it")
}, defaultErrorFun)
}
private fun sendMessage(socket: DatagramSocket, host: String, port: Int) : Single<Boolean> {
val throwable: Throwable
val message = "Hello"
val hostAddress = InetAddress.getByName(host)
val buf = message.toByteArray()
try {
logger.d("Current thread: ${Thread.currentThread().name}")
val packet = DatagramPacket(buf, buf.size, hostAddress, port)
socket.send(packet)
logger.d("Sent message: $message")
return Single.just(true)
} catch (e: SocketException) {
throwable = e
e.printStackTrace()
} catch (e: UnknownHostException) {
throwable = e
e.printStackTrace()
} catch (e: IOException) {
throwable = e
e.printStackTrace()
} catch (e: Exception) {
throwable = e // <=== This is where I get Exception
e.printStackTrace()
}
return Single.error(throwable)
}
}
我不知道到底是什么问题。您的sendMessage()
是一个在同步调用时同步执行的函数
只有您创建的Single
将在IO线程上执行,但您只有常量值Single.just()
(和Single.error()
)可返回,因此在IO调度程序上确实没有可执行的代码
实际上,您必须提供一个代码块来构建您的单
。例如,将代码包装在Single.fromCallable{}
中,而不是使用Single.just()
您的sendMessage()
是一个在同步调用时同步执行的函数
只有您创建的Single
将在IO线程上执行,但您只有常量值Single.just()
(和Single.error()
)可返回,因此在IO调度程序上确实没有可执行的代码
实际上,您必须提供一个代码块来构建您的
单
。例如,将代码包装在Single.fromCallable{}
中,而不是使用Single.just()
谢谢你的回答@laaltoSingle.just(true)
在发生位置错误的socket.send(packet)
之后被调用。因此,Single.just(true)
不会被调用。另一件事是,根据我的underestanding,当我设置.subscribeOn(Schedulers.io())
时,必须在io线程中调用sendMessage()。这就是让我困惑的地方。是的,在到达Single.just()
之前有一个异常subscribeOn()
etc.影响您返回的可观察对象,而不是创建它的代码。太棒了,谢谢您的解释。我做了一个快速搜索,找到了作为参考。因此,这是我为那些有类似错误的人所做的修复:Single.fromCallable{sendMessage(socket,UDP_主机,UDP_端口)}
谢谢你的回答@laaltoSingle.just(true)
在发生位置错误的socket.send(packet)
之后被调用。因此,Single.just(true)
不会被调用。另一件事是,根据我的underestanding,当我设置.subscribeOn(Schedulers.io())
时,必须在io线程中调用sendMessage()。这就是让我困惑的地方。是的,在到达Single.just()
之前有一个异常subscribeOn()
etc.影响您返回的可观察对象,而不是创建它的代码。太棒了,谢谢您的解释。我做了一个快速搜索,找到了作为参考。因此,这是我为那些有类似错误设置的人所做的修复:Single.fromCallable{sendMessage(socket,UDP_主机,UDP_端口)}
fun <T> applySingleAsync(): SingleTransformer<T, T> {
return SingleTransformer { observable ->
observable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
}
}