Jetpack Compose 在 ViewModel 中更新状态,其中状态是集合。

huangapple go评论47阅读模式
英文:

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组件显示问题和答案,并接受一个用于更新答案的回调。

您的问题是如何在TextFieldonValueChange中传递两个参数:问题文本和答案值,以便在更新方法中找到正确的状态并更新状态值。

英文:

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&lt;QuestionnaireViewModel.AnswerState&gt;,
  onAnswerTextChange: (String, String) -&gt; Unit = {},
) {
  Column (
    modifier = Modifier.padding(15.dp),
    verticalArrangement = Arrangement.spacedBy(10.dp)
  ) {
    state.forEach { questionAnswer -&gt;
      QuestionCard(
        answerState = questionAnswer,
        onAnswerTextChange = { newAnswer -&gt; 
          onAnswerTextChange.invoke(questionAnswer.question, newAnswer)
        }
      )
    }
  }
}

huangapple
  • 本文由 发表于 2023年4月6日 20:05:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/75949325.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定