我设置了subscriptionOn(Schedulers.io())

时间:2019-01-30 19:38:18

标签: android rx-java2

基于我对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())
    }
}

我不知道到底是什么问题。

1 个答案:

答案 0 :(得分:2)

您的sendMessage()是一个在您同步调用时同步执行的函数。

只有创建的Single会在IO线程上执行,但是返回的常量只有Single.just()(和Single.error()),因此实际上没有任何代码可以执行IO调度程序。

实际上,您实际上必须提供一个代码块才能从中构造Single。例如,将代码包装在Single.fromCallable { }中,而不要使用Single.just()