Setstate 不会在颤振中更新 UI

时间:2021-04-06 19:14:25

标签: android flutter flutter-layout

我正在根据 JSON 数据构建表单。我遍历问题列表并生成单选按钮。我将单选按钮选择的值存储在 formDatas 列表中。

单选按钮值在 formDatas 中更新,但用户界面在选择后没有更新,我不确定我错过了什么

class Questionnaire extends StatefulWidget {
  @override
  _QuestionnaireState createState() => _QuestionnaireState();
}

class _QuestionnaireState extends State<Questionnaire> {
  final GlobalKey<FormState> formKey = GlobalKey<FormState>();
  List<Widget> fieldList = [];
  List<dynamic> questions = [
    {
      "minLabel": {"en": "default"},
      "maxValue": null,
      "type": "SWITCH",
      "weightLogics": [],
      "maxLabel": {"en": "default"},
      "enabled": false,
      "points": null,
      "minValue": null,
      "includeInScore": false,
      "intro": {"en": "default"},
      "name": "",
      "options": [
        {
          "id": "jhjhkjhk",
          "choiceFeedback": "true",
          "correct": false,
          "choiceText": {"en": "Yes"},
          "value": 0.0,
          "seq": 0.0
        },
        {
          "id": "sjgjsf",
          "choiceFeedback": "false",
          "correct": false,
          "choiceText": {"en": "No"},
          "value": 0.0,
          "seq": 1.0
        }
      ],
      "id": "0sdlfsdf",
      "text": {"en": "Are you new"}
    },
  ];
  List<Map<String, dynamic>> formDatas = [];
  void initState() {
    super.initState();
    questions.forEach((question) {
      Map<String, dynamic> data = {'questionId': question["id"], 'value': ''};
      formDatas.add(data);
    });

    fieldList = createFields();
  }


  List<Widget> createFields() {
      questions.forEach((question) {
        if (question['type'] == 'SWITCH') {
          fieldList.add(createRadioFields(question));
        }
      });
    return fieldList;
  }

  Widget createRadioFields(question) {
    final index = formDatas.indexWhere((element) => element["questionId"] == question["id"]);
    return Container(
      margin: EdgeInsets.all(15.0),
      decoration: BoxDecoration(
        border: Border(bottom: BorderSide(color: Colors.grey, width: 1))
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          new Text(
            question["text"]["en"],
            style: TextStyle(color: Colors.blue),
          ),
          Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: question['options']
                  .map<Widget>((option) => RadioListTile(
                      title: Text(option["choiceText"]["en"]),
                      value: option["choiceFeedback"],
                      groupValue: formDatas[index]["value"],
                      onChanged: (value) {
                        setState(() {
                          print(value);
                          formDatas[index]["value"] = value;
                          formDatas = formDatas;
                        });
                      }))
                  .toList())
        ],
      ),
    );
  }

  Widget createForm() {
    return Form(
        key: formKey,
        child: SingleChildScrollView(
          child: Column(children: fieldList),
        ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Questionnaire'),
        ),
        body: createForm());
  }
}

1 个答案:

答案 0 :(得分:0)

如果 createFields() 只在 initState() 中调用,这只会在第一次构建时运行一次。之后,它将永远不会再被调用。 setState() 将再次调用 build() 方法,但不会调用 initState

因此,将 createFields()initState 移到 build()

  void initState() {
    super.initState();
    questions.forEach((question) {
      Map<String, dynamic> data = {'questionId': question["id"], 'value': ''};
      formDatas.add(data);
    });

    //fieldList = createFields(); // move this into build ↓  ************
  }

StatefulWidget 的 build() 方法:

  @override
  Widget build(BuildContext context) {
    fieldList = createFields(); // ← re/build fields ************

    return Scaffold(
        appBar: AppBar(
          title: Text('Questionnaire'),
        ),
        body: createForm());
  }