Я хочу вызвать функцию приостановки внутри обратного вызова составной функции.
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")
}
}
Если бы я использовал Rx, я бы просто subscribe
.
Я мог бы сделать invokeOnCompletion
, а затем getCompleted
, но этот API экспериментальный.
Я не могу использовать launchInComposition
в getLocationOnClick
, потому что launchInComposition
равно @Composable
, а getLocationOnClick
не может быть @Composable
.
Как лучше всего получить результат приостановки функции внутри обычной функции, внутри функции @Composable
?
2 ответа
Создайте область сопрограмм, привязанную к жизненному циклу вашего составного объекта, и используйте эту область для вызова функции приостановки.
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")
}
}
Вы можете использовать viewModelScope ViewModel или любую другую область сопрограммы.
Пример удаления действия для элемента из LazyColumnFor, который требует приостановки вызова, обрабатываемого ViewModel.
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 }
)
}
}
Похожие вопросы
Новые вопросы
android
Android - это мобильная операционная система Google, используемая для программирования или разработки цифровых устройств (смартфоны, планшеты, автомобили, телевизоры, одежда, стекло, IoT). Для тем, связанных с Android, используйте специальные теги Android, такие как android-intent, android-activity, android-адаптер и т. Д. Для вопросов, не связанных с разработкой или программированием, но связанных с платформой Android, используйте эту ссылку: https: // android.stackexchange.com .