Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

656
Views
¿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 answers
Answer question

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 Report

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 Report

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!