如何在jetpack compose中的后台线程上运行函数?

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

我在 Android 应用程序中遇到这样的情况:某些计算偶尔会导致 NumberFormatException。为了解决这个问题,我实现了 Try Catch 块,它有效地解决了这个问题。然而,这个解决方案导致了另一个问题——由于 UI 阻塞而导致 ANR(应用程序未响应)。经过一番调查,我了解到 Try Catch 块导致 UI 阻塞,从而导致 ANR。

我的问题是:如何在单独的后台线程上使用 Try Catch 来防止它阻塞主 UI?值得注意的是,Try Catch 块中的函数主要用于数学计算。下面是我最初实现的相关代码片段:

第一个例子:

val areaInSqMeter: Double? = try {
                                SphericalUtil.computeArea(geoPoints)
                            } catch (e: Exception) {
                                Log.e("MapScreen", "$e")
                                null
                            }

areaInSqMeter?.let {
   // updating viemodel variables and showing data
  }

第二个例子:

try {
                        if (isTriangleValid(
                                viewModel.sideA,
                                viewModel.sideB,
                                viewModel.sideC,
                                viewModel.sideD,
                                viewModel.sideE
                            )
                        ) {
                            // calculate the area
                            viewModel.selectedTerritory?.let {
                                calculateAreaAndCadastralAndUpdateViewModel(
                                    viewModel = viewModel,
                                    selectedTerritoryCode = it,
                                    context = manualMeasurementCompactScreenContext
                                )

                                focusManager.clearFocus(true)
                                keyboardController?.hide()
                            }

                        } else {
                            Toast.makeText(
                                manualMeasurementCompactScreenContext,
                                invalidValuesToast,
                                Toast.LENGTH_SHORT
                            ).show()
                        }
                    } catch (e: NumberFormatException) {
                        Toast.makeText(
                            manualMeasurementContext,
                            manualMeasurementContext.getString(R.string.toast_error_number_format_error),
                            Toast.LENGTH_SHORT
                        ).show()
                    }
kotlin android-jetpack-compose android-threading
1个回答
0
投票

为了不阻塞 UI,您可以使用视图模型中的协程作用域,并根据需要指定调度程序,如下所示:

viewModelScope.launch(Dispatchers.Default) {
val areaInSqMeter: Double? = try {
                            SphericalUtil.computeArea(geoPoints)
                        } catch (e: Exception) {
                            Log.e("MapScreen", "$e")
                            null
                        }

areaInSqMeter?.let {
   // updating viemodel variables and showing data
  }
}

您还可以使用 withContext() 而不是视图模型范围,如下所示:

withContext(Dispatchers.Default) {              
    
}  

假设您的计算任务与CPU密集型工作相关,您可以使用Dispacthers.Default代替IO,因为稍后它用于网络和读/写操作。您可以从此处的官方文档了解有关此主题的更多信息:https://developer.android.com/kotlin/coroutines/coroutines-adv

如果您在 UI 中想要等待结果,那么您可以将其与 LaunchedEffect 配对并提供适当的密钥以进行重组。这是我的代码中的一个示例:

LaunchedEffect(key1 = Unit, block = {
    this.async(Dispatchers.Default) {
        try {
            extractVideoFrames(Constants.BASE_URL + clipInfo.videoURL, clipBuilderViewModel)
        } catch (e: Exception) {
            Timber.e("Extracting video frames failed with exception: ${e.message}")
        }
    }.await()
})
© www.soinside.com 2019 - 2024. All rights reserved.