草庐IT

android - NetworkOnMainThreadException 是否对协程中的网络调用有效?

coder 2023-12-21 原文

我正在使用 Kotlin for Android 构建一个简单的演示应用程序,它使用 Jsoup 检索网页的标题。我正在使用 Dispatchers.Main 作为上下文进行网络调用。

我对协程的理解是,如果我在 Dispatchers.Main 上调用 launch,它在主线程上运行,但会暂停执行以免阻塞线程。

我对android.os.NetworkOnMainThreadException的理解是因为网络操作繁重,在主线程上运行会阻塞。

所以我的问题是,如果协程不会阻塞运行它的线程,NetworkOnMainThreadException 真的有效吗?以下是在 Jsoup.connect(url).get() 处抛出给定异常的一些示例代码:

class MainActivity : AppCompatActivity() {
    val job = Job()

    val mainScope = CoroutineScope(Dispatchers.Main + job)

    // called from onCreate()
    private fun printTitle() {
        mainScope.launch {
            val url ="https://kotlinlang.org"
            val document = Jsoup.connect(url).get()
            Log.d("MainActivity", document.title())
            // ... update UI with title
        }
    }
}

我知道我可以简单地使用 Dispatchers.IO 上下文运行它并将此结果提供给主/UI 线程,但这似乎避开了协程的一些实用程序。

作为引用,我使用的是 Kotlin 1.3。

最佳答案

My understanding of coroutines is that if I call launch on the Dispatchers.Main it does run on the main thread, but suspends the execution so as to not block the thread.

为了不阻塞线程而暂停执行的唯一点是标记为 suspend 的方法 - 即,暂停方法。

由于 Jsoup.connect(url).get() 不是挂起方法,它会阻塞当前线程。当您使用 Dispatchers.Main 时,当前线程是主线程,您的网络操作直接在主线程上运行,导致 NetworkOnMainThreadException

get() 方法这样的阻塞工作可以通过将其包装在 withContext() 中来暂停,一个暂停方法并且确保 Dispatchers.Main 在方法运行时不会被阻塞。

mainScope.launch {
    val url ="https://kotlinlang.org"
    val document = withContext(Dispatchers.IO) {
        Jsoup.connect(url).get()
    }
    Log.d("MainActivity", document.title())
    // ... update UI with title
}

关于android - NetworkOnMainThreadException 是否对协程中的网络调用有效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53582860/

有关android - NetworkOnMainThreadException 是否对协程中的网络调用有效?的更多相关文章

随机推荐