我只想在加載可組合項時運行代碼一次。所以我使用 LaunchedEffect 和 key as true 來實作這一點。
LaunchedEffect(true) {
// do API call
}
這段代碼作業正常,但只要有任何配置更改(如螢屏旋轉),就會再次執行此代碼。如果配置更改,如何防止它再次運行?
uj5u.com熱心網友回復:
最簡單的解決方案是存盤有關您是否通過以下方式進行 API 呼叫的資訊rememberSaveable:當配置更改時,它將存在。
var initialApiCalled by rememberSaveable { mutableStateOf(false) }
if (!initialApiCalled) {
LaunchedEffect(Unit) {
// do API call
initialApiCalled = false
}
}
這種解決方案的缺點是,如果在 API 呼叫完成之前配置發生變化,LaunchedEffect協程將被取消,您的 API 呼叫也會被取消。
最干凈的解決方案是使用視圖模型,并在內部執行 API 呼叫init:
class ScreenViewModel: ViewModel() {
init {
viewModelScope.launch {
// do API call
}
}
}
@Composable
fun Screen(viewModel: ScreenViewModel = viewModel()) {
}
像這樣傳遞視圖模型作為引數,官方檔案推薦。在 prod 代碼中,您不需要向此視圖傳遞任何引數,只需像這樣呼叫它Screen():視圖模型將通過默認viewModel()引數創建。它被移動到測驗/預覽功能的引數,如本答案所示。
uj5u.com熱心網友回復:
我認為最好的方法是在 livedata/stateflow 延遲創建上使用 .also,這樣您就可以保證只要視圖模型處于活動狀態,loadState 只會被呼叫一次,并且還保證不會呼叫服務本身,除非有人在聽。然后你從視圖模型中監聽狀態,不需要從啟動的效果中呼叫任何 api 呼叫,你的代碼也會對特定狀態做出反應。
這是一個代碼示例
class MyViewModel : ViewModel() {
private val uiScreenState: : MutableStateFlow<WhatEverState> =
MutableStateFlow(WhatEverIntialState).also {
loadState()
}
fun loadState(): StateFlow<WhatEverState>> {
return users
}
private fun loadUsers() {
// Do an asynchronous operation to fetch users.
}
}
使用此代碼時,您根本不必在活動中呼叫 loadstate,您只需聆聽觀察者的聲音即可。
您可以查看以下代碼進行收聽
class MyFragment : Fragment {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return ComposeView(requireContext()).apply {
setContent {
StartingComposeTheme {
Box(modifier = Modifier.fillMaxSize()) {
val state by viewModel.uiScreenState.collectAsState()
when (state) {
//do something
}
}
}
}
}
}
}}
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/324781.html
標籤:安卓 科特林 android-jetpack-compose android-jetpack
