基于我对RxJava的理解,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)
}
}
这是由以上代码组成的applySingleAsync
:
fun <T> applySingleAsync(): SingleTransformer<T, T> {
return SingleTransformer { observable ->
observable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
}
}
我不知道到底是什么问题。
答案 0 :(得分:2)
您的sendMessage()
是一个在您同步调用时同步执行的函数。
只有创建的Single
会在IO线程上执行,但是返回的常量只有Single.just()
(和Single.error()
),因此实际上没有任何代码可以执行IO调度程序。
实际上,您实际上必须提供一个代码块才能从中构造Single
。例如,将代码包装在Single.fromCallable { }
中,而不要使用Single.just()
。