我有 2 個可變狀態,ViewModel并希望他們觀察我的可組合中的文本欄位。
ViewModel:
@HiltViewModel
class AddEditTransactionViewModel @Inject constructor(
private val moneyManagerUseCases: MoneyManagerUseCases
) : ViewModel() {
private val _transactionDescription = mutableStateOf("")
val transactionDescription: State<String> = _transactionDescription
private val _transactionAmount = mutableStateOf("")
val transactionAmount: State<String> = _transactionAmount
Composable:
@Composable
fun AddEditTransactionScreen(
navController: NavController,
viewModel: AddEditTransactionViewModel = hiltViewModel(),
) {
// This works
var descriptionState by remember { mutableStateOf("") }
var amountState by remember { mutableStateOf("") }
// This doesn't work
var viewModelDescriptionState = viewModel.transactionDescription.value
var viewModelAmountState = viewModel.transactionAmount.value
Column(
modifier = Modifier
.fillMaxSize()
.padding(8.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
TextField(
value = viewModelDescriptionState,
onValueChange = { viewModelDescriptionState = it },
label = { Text(text = "Description") })
Spacer(modifier = Modifier.padding(20.dp))
TextField(
value = viewModelAmountState,
onValueChange = { viewModelAmountState = it },
label = { Text(text = "Amount") },
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number)
)
如果我使用我的可組合中的狀態,它會起作用,但這種效果會超出 ViewModel 的目的。
uj5u.com熱心網友回復:
第一行:
var descriptionState by remember { mutableStateOf(") }
它有效是因為您正在更新mutableStatevia 委托的值。如果你看看在沒有委托的情況下你會如何做,會更容易理解:
val descriptionState = remember { mutableStateOf("") }
//...
descriptionState.value = "new value"
remember將在重新組合之間保存相同的物件,但該物件的value欄位正在發生變化。
另一方面,這里:
var viewModelDescriptionState = viewModel.transactionDescription.value
您創建了一個區域變數,并且在重新組合之間不會保存任何更改。
這通常通過在視圖模型中創建一個 setter 函式來解決。你也可以在視圖模型中使用委托,如果你想限制它在沒有 setter 的情況下更新,你可以添加private set, 而不是有private _variableand public variable:
var transactionDescription by mutableStateOf("")
private set
fun updateTransactionDescription(newValue: String) {
transactionDescription = newValue
}
這被認為是最佳實踐,因為 setter 可以包含比簡單更新值更多的邏輯。在只需要存盤的情況下,可以去掉private部分直接更新,不需要setter函式。
您可以在Compose檔案中找到有關狀態的更多資訊,包括解釋基本原理的這個 youtube 視頻。
uj5u.com熱心網友回復:
解決方案
AddEditTransactionScreen:
@Composable
fun AddEditTransactionScreen(
navController: NavController,
viewModel: AddEditTransactionViewModel = hiltViewModel()
) {
val descriptionState = viewModel.transactionDescription
val amountState = viewModel.transactionAmount
Column(
modifier = Modifier
.fillMaxSize()
.padding(8.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
TextField(
value = descriptionState.value,
onValueChange = { viewModel.updateTransactionDescription(it) },
label = { Text(text = "Description") })
Spacer(modifier = Modifier.padding(20.dp))
TextField(
value = amountState.value,
onValueChange = { viewModel.updateTransactionAmount(it) },
label = { Text(text = "Amount") },
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number)
)
}
}
AddEditTransactionViewModel:
@HiltViewModel
class AddEditTransactionViewModel @Inject constructor() : ViewModel() {
private val _transactionDescription = mutableStateOf("")
val transactionDescription: State<String> = _transactionDescription
private val _transactionAmount = mutableStateOf("")
val transactionAmount: State<String> = _transactionAmount
fun updateTransactionDescription(value: String) {
_transactionDescription.value = value
}
fun updateTransactionAmount(value: String) {
_transactionAmount.value = value
}
}
解釋
它transactionDescription和transactionAmount屬性是State<String>型別,State型別不能改變它的值,與MutableState型別不同,一個簡單的解決方案只通過視圖模型維護更改保護,為每個要更改的屬性創建一個方法并進行此更改在屬性中MutableState。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/393742.html
