Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

665
Vistas
¿Cómo llamar a Kotlin coroutine en devoluciones de llamada de funciones componibles?

Quiero llamar a una función de suspensión dentro de una devolución de llamada de función componible.

 suspend fun getLocation(): Location? { /* ... */ } @Composable fun F() { val (location, setLocation) = remember { mutableStateOf<Location?>(null) } val getLocationOnClick: () -> Unit = { /* setLocation __MAGIC__ getLocation */ } Button(onClick = getLocationOnClick) { Text("detectLocation") } }

Si hubiera usado Rx, entonces podría simplemente subscribe .

Podría invokeOnCompletion y luego getCompleted , pero esa API es experimental.

No puedo usar launchInComposition en getLocationOnClick porque launchInComposition es @Composable y getLocationOnClick no puede ser @Composable .

¿Cuál sería la mejor manera de obtener el resultado de una función de suspensión dentro de una función normal, dentro de la función @Composable ?

over 4 years ago · Hanz Gallego
3 Respuestas
Responde la pregunta

0

Esto funciona para mí:

 @Composable fun TheComposable() { val coroutineScope = rememberCoroutineScope() val (loadResult, setLoadResult) = remember { mutableStateOf<String?>(null) } IconButton( onClick = { someState.startProgress("Draft Loading...") coroutineScope.launch { withContext(Dispatchers.IO) { try { loadResult = DataAPI.getData() // <-- non-suspend blocking method } catch (e: Exception) { // handle exception } finally { someState.endProgress() } } } } ) { Icon(Icons.TwoTone.Call, contentDescription = "Load") }

También probé la siguiente función de ayuda, para forzar a los colegas desarrolladores a manejar Excepciones y finalmente limpiar el estado (también para hacer el mismo código (¡quizás!?) un poco más corto y (¡quizás!?) un poco más legible):

 fun launchHelper(coroutineScope: CoroutineScope, catchBlock: (Exception) -> Unit, finallyBlock: () -> Unit, context: CoroutineContext = EmptyCoroutineContext, start: CoroutineStart = CoroutineStart.DEFAULT, block: suspend CoroutineScope.() -> Unit ): Job { return coroutineScope.launch(context, start) { withContext(Dispatchers.IO) { try { block() } catch (e: Exception) { catchBlock(e) } finally { finallyBlock() } } } }

y he aquí cómo usar ese método auxiliar:

 @Composable fun TheComposable() { val coroutineScope = rememberCoroutineScope() val (loadResult, setLoadResult) = remember { mutableStateOf<String?>(null) } IconButton( onClick = { someState.startProgress("Draft Loading...") launchHelper(coroutineScope, catchBlock = { e -> myExceptionHandling(e) }, finallyBlock = { someState.endProgress() } ) { loadResult = DataAPI.getData() // <-- non-suspend blocking method } } ) { Icon(Icons.TwoTone.Call, contentDescription = "Load") } }
over 4 years ago · Hanz Gallego Denunciar

0

Puede usar viewModelScope de un ViewModel o cualquier otro ámbito de rutina.

Ejemplo de acción de eliminación para un elemento de LazyColumnFor que requiere una llamada de suspensión manejada por un modelo de vista.

 class ItemsViewModel : ViewModel() { private val _itemList = MutableLiveData<List<Any>>() val itemList: LiveData<List<Any>> get() = _itemList fun deleteItem(item: Any) { viewModelScope.launch(Dispatchers.IO) { TODO("Fill Coroutine Scope with your suspend call") } } } @Composable fun Example() { val itemsVM: ItemsViewModel = viewModel() val list: State<List<Any>?> = itemsVM.itemList.observeAsState() list.value.let { it: List<Any>? -> if (it != null) { LazyColumnFor(items = it) { item: Any -> ListItem( item = item, onDeleteSelf = { itemsVM.deleteItem(item) } ) } } // else EmptyDialog() } } @Composable private fun ListItem(item: Any, onDeleteSelf: () -> Unit) { Row { Text(item.toString()) IconButton( onClick = onDeleteSelf, icon = { Icons.Filled.Delete } ) } }
over 4 years ago · Hanz Gallego Denunciar

0

Cree un alcance de rutinas, vinculado al ciclo de vida de su componible, y use ese alcance para llamar a su función de suspensión

 suspend fun getLocation(): Location? { /* ... */ } @Composable fun F() { // Returns a scope that's cancelled when F is removed from composition val coroutineScope = rememberCoroutineScope() val (location, setLocation) = remember { mutableStateOf<Location?>(null) } val getLocationOnClick: () -> Unit = { coroutineScope.launch { val location = getLocation() } } Button(onClick = getLocationOnClick) { Text("detectLocation") } }
over 4 years ago · Hanz Gallego Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda