用作 LaunchedEffect 键时出现 NetworkOnMainThreadException

问题描述 投票:0回答:3

当我使用时

 LaunchedEffect(Dispatchers.IO) 

我明白了,

网络主线程异常

我应该如何使用这个函数在后台线程上运行?

这是我的代码:

LaunchedEffect(Dispatchers.IO) {
    val input = URL("https://rezaapp.downloadseriesmovie.ir/maintxt.php").readText()
    println(input)
}

我在我的 jetpack compose 项目中使用它

android kotlin android-jetpack-compose kotlin-coroutines side-effects
3个回答
3
投票

LaunchedEffect
是 Jetpack Compose 中的众多 Side Effects 之一,但我们最好只拥有非常简单的 compose 用例,而不是仅仅解释。尽管我希望您已经知道什么是
re-composition
以及
MutableState
如何触发它。

我们将拥有:

  • 中间有一个按钮的屏幕
  • a
    MutableState
    可递增的整数值
  • 里面的Log语句
    LaunchedEffect

我们会做什么

  • 单击按钮并增加
    MutableState
    整数值
  • 打印增加的值

我们会期待什么

  • Logcat 将显示来自
    LaunchedEffect
    的值,甚至在单击按钮之前

我们的简单

Composable

@Composable
fun ComposeSample() {

    var intNum by remember {
        mutableStateOf(0)
    }

    Box(
        modifier = Modifier
            .fillMaxSize(),
        contentAlignment = Alignment.Center
    ) {
         Button(onClick = {
             intNum++
         }) {
             Text(
                 text = "Increment the integer"
             )
         }
    }

    LaunchedEffect(Unit) {
        Log.e("IntNumber", "Current value: $intNum")
    }
}

此时,请注意我随

key
提供的
LaunchedEffect

当第一次渲染屏幕时,

LaunchedEffect
将触发,我们将看到 logcat 打印。

E: Current value: 0

但是当我单击按钮时,它没有显示增加的值。因为

LaunchedEffect
需要一个
key
,如果您打算每隔
re-composition
触发它,它就会改变。

现在我使用

key
LaunchedEffect
变量更改了提供给
MutableState
intNum

LaunchedEffect(intNum) {
    Log.e("IntNumber", "Current value: $intNum")
}

每次点击logcat都会打印,因为每次

intNum
发生变化时,都会触发
LaunchedEffect
,从而触发Logcat语句。

E: Current value: 0
E: Current value: 1
E: Current value: 2
E: Current value: 3

key
中的
LaunchedEffect
发生变化并且发生
composition
时,它将触发其块内的任何内容。

我不确定您想通过发布的代码实现什么目标,我什至不知道它是如何发生的,但我想没有任何用例(据我所知)您可以使用特定的协程调度程序作为

LaunchedEffect
key


0
投票

让我直接清楚地告诉你,

  • lifecyclescope
    ,或 compose ui 中的任何
    coroutine scope
    位于 main 上 默认线程。
  • 特别是对于 compose 协程作用域,您无法更改它们 调度员,

我强烈建议您调用 ViewModel 方法,然后在

viewmodelSope
中启动协程,还要记住,撰写协程作用域用于轻度挂起操作,不要在这些作用域中执行任何繁重的操作。


0
投票

您应该先看看 LaunchedEffect 做了什么。在您的代码中,您将

Dispatchers.IO
作为键而不是作为要使用的调度程序。

由于 LaunchedEffect 将有一个

CoroutineScope.() -> Unit
块,您可以在该块内切换线程,如下所示:

LaunchedEffect {
    launch(Dispatchers.IO) {
        val input = URL("https://rezaapp.downloadseriesmovie.ir/maintxt.php").readText()
        println(input)
    }
}

希望这就是您正在寻找的。

© www.soinside.com 2019 - 2024. All rights reserved.