英文:
Jetpack Compose Updating state in ViewModel where state is collection
问题
Sure, here's the translation of the code part you provided without the code itself:
我有一个ViewModel和一个屏幕,用于创建问题列表并具有用于回答的输入。
在我的ViewModel中:
- 我有一个名为
QuestionnaireViewModel
的@HiltViewModel
,它通过构造函数注入了_questionRepository
。 - 我定义了
AnswerState
数据类,包含问题和答案。 - 我获取问题列表,并根据问题创建答案状态列表。
- 我使用
MutableStateFlow
来管理视图状态。
在我的屏幕中:
- 我使用
@OptIn(ExperimentalMaterial3Api::class)
注解。 - 我创建了
QuestionnaireScreen
组件,获取了QuestionnaireViewModel
的实例,并收集了视图状态。 - 在
QuestionnaireScreen
中,我使用Questionnaire
组件来显示问题和答案。 Questionnaire
组件接受一个问题状态列表以及一个用于更新答案的回调。QuestionCard
组件显示问题和答案,并接受一个用于更新答案的回调。
您的问题是如何在TextField
的onValueChange
中传递两个参数:问题文本和答案值,以便在更新方法中找到正确的状态并更新状态值。
英文:
I have a ViewModel and screen which creates a list pf questions and has input for answers
@HiltViewModel
class QuestionnaireViewModel @Inject constructor (
private val _questionRepository: QuestionRepository
): ViewModel() {
data class AnswerState(
val question: String,
var answer: String
)
val questions: List<Questions> = _questionRepository.getQuestions("pole1")
val questionAnswers = questions.map { q -> AnswerState(q.qText, "") }
private val _viewState = MutableStateFlow<List<AnswerState>>(questionAnswers)
val viewState = _viewState.asStateFlow()
fun updateAnswer(question: String, answer: String) {
val updatedAnswerState = _viewState.value.toMutableList()
updatedAnswerState .filter { as -> as.question == question }.get(0).answer = answer
_viewState.value = updatedAnswerState
}
So then in my screen
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun QuestionnaireScreen() {
val viewModel: QuestionnaireViewModel = hiltViewModel()
val state by viewModel.viewState.collectAsState()
Column(modifier = Modifier) {
Text(...Some elements)
Questionnaire(
state = state,
onAnswerTextChange = viewModel::updateAnswer,
)
}
}
@Composable
private fun Questionnaire(
modifier: Modifier = Modifier,
state: List<QuestionnaireViewModel.AnswerState>,
onAnswerTextChange: (String) -> Unit = {},
) {
Column (
modifier = Modifier.padding(15.dp),
verticalArrangement = Arrangement.spacedBy(10.dp)
) {
state.forEach { questionAnswer ->
QuestionCard(
answerState = questionAnswer,
onAnswerTextChange = onAnswerTextChange
)
}
}
}
@Composable
fun QuestionCard(
answerState: QuestionnaireViewModel.AnswerState,
onAnswerTextChange: (String) -> Unit = {}
) {
Column (
modifier = Modifier.fillMaxWidth()
) {
Text (
text = answerState.question
)
TextField(
value = answerState.answer,
onValueChange = onAnswerTextChange
)
}
}
So how do I supply two params from my textfield onValueChange, one being the question text to locate the correct piece of state in my update method and then the actual value to update the state value? Kind Regards,
答案1
得分: 0
@Composable
private fun Questionnaire(
modifier: Modifier = Modifier,
state: List<QuestionnaireViewModel.AnswerState>,
onAnswerTextChange: (String, String) -> Unit = {}
) {
Column (
modifier = Modifier.padding(15.dp),
verticalArrangement = Arrangement.spacedBy(10.dp)
) {
state.forEach { questionAnswer ->
QuestionCard(
answerState = questionAnswer,
onAnswerTextChange = { newAnswer ->
onAnswerTextChange.invoke(questionAnswer.question, newAnswer)
}
)
}
}
}
英文:
Can't you just change your lambda to take 2 strings, like so?
@Composable
private fun Questionnaire(
modifier: Modifier = Modifier,
state: List<QuestionnaireViewModel.AnswerState>,
onAnswerTextChange: (String, String) -> Unit = {},
) {
Column (
modifier = Modifier.padding(15.dp),
verticalArrangement = Arrangement.spacedBy(10.dp)
) {
state.forEach { questionAnswer ->
QuestionCard(
answerState = questionAnswer,
onAnswerTextChange = { newAnswer ->
onAnswerTextChange.invoke(questionAnswer.question, newAnswer)
}
)
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论