动态/列表/​​数组变量抖动上的setState

时间:2019-09-15 02:58:55

标签: arrays flutter dart state

我知道这有点混乱,并且我对flutter很陌生,我很了解状态如何在react上表现出来,但是flutter上的状态管理在数组变量上表现出不同的表现。

当我尝试使用其他方法设置状态时,它给了我不同的错误消息。我已经在这个特定的小部件上工作了一个星期,但仍然不知道我在哪里做错了。


class SurveyCard extends StatefulWidget {
  final int argument;
  SurveyCard({Key key, this.argument}) : super(key: key);
  State<StatefulWidget> createState() {
    return _Survey(argument: argument);
  }
}

class _Survey extends State<SurveyCard> {
  List<int> _value1=[];
  int argument;
  _Survey({Key key, this.argument});
  int value0=0;
  List<File> _file=[];

  void choose(i) async {
    var file;
    file = await ImagePicker.pickImage(source: ImageSource.camera);
    // giving me error when i take a picture.NoSuchMethodError (NoSuchMethodError: The method '[]=' was called on null. Receiver: nullTried calling: []=(0, Instance of '_File'))
    setState(() => _file[i] = file);
  }
  //cond 1 i can't press the radio button
  void _setvalue1(int value, i) { 
    setState(() {
     _value1[i]=value; 
    });
    }
  // cond 2  doesn't work and giving me rangeerror invalid value
  // _setvalue1(int value, i) { 
  //   setState(() {
  //    _value1[i]=value; 
  //   });
  // } 

  Widget makeRadioTiles(data, index) {
    List<Widget> list = new List<Widget>();

    for (int i = 0; i < data.length; i++) {
      int id = data[i].answerID;
      list.add(new RadioListTile(
        value: id,
        groupValue: _value1,
        // cond1
        onChanged:(id) => _setvalue1(id, index),
        // cond 2
        // onChanged: _setvalue1(id, index), 
        activeColor: Colors.green,
        controlAffinity: ListTileControlAffinity.trailing,
        title: new Text('${data[i].answerName}'),
      ));
    }
    Column column = new Column(
      children: list,
    );
    return column;
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return BaseWidget<VesselScreenModel>(
        model: VesselScreenModel(api: Provider.of(context)),
        onModelReady: (model) => model.getQuestion(argument),
        builder: (context, model, child) => model.busy
            ? Center(child: new CircularProgressIndicator())
            : ListView.builder(
                padding: const EdgeInsets.all(32),
                scrollDirection: Axis.vertical,
                shrinkWrap: true,
                itemCount: model.questions.data.questions.length,
                itemBuilder: (context, i) {
                  var dataSnapshot = model.questions;
                  var snapshot = dataSnapshot.data.questions[i];
                  return Card(
                    color: Colors.white,
                    child: Column(
                      children: [
                        Center(
                          child: _file == null
                              ? Text('No image selected.')
                              : Image.file(_file[i]),
                        ),
                        ListTile(
                            title: Text('${snapshot.questionName}',
                                style: TextStyle(
                                    fontWeight: FontWeight.w900,
                                    color: Colors.black))),
                        Column(
                          children: <Widget>[
                            makeRadioTiles(snapshot.answers, i)
                          ],
                        ),
                        Container(
                          padding: const EdgeInsets.only(left: 16, right: 16),
                          child: TextField(
                            decoration: InputDecoration(labelText: 'Comment'),
                          ),
                        ),
                        Align(
                          alignment: Alignment.centerLeft,
                          child: Container(
                            child: FlatButton(
                                color: Color.fromRGBO(105, 114, 100, 0),
                                //where i take a picture for image
                                onPressed: () => choose(i),
                                child: const Text('Upload Image',
                                    style: TextStyle(fontSize: 15))),
                          ),
                        ),
                      ],
                    ),
                  );
                },
              ));
  }
}

1 个答案:

答案 0 :(得分:0)

您正在使用固定大小的列表_value1_file。当您知道数组索引的上限时,请考虑使用它们的大小初始化这两个列表。

为了使它正常工作,我已经对您的代码进行了一些修改。


class SurveyCard extends StatefulWidget {
  final int argument;
  SurveyCard({Key key, this.argument}) : super(key: key);
  State<StatefulWidget> createState() {
    return _Survey(argument: argument);
  }
}

class _Survey extends State<SurveyCard> {
  //Instead of initialzing your lists here
  //initilize them inside itembuilder 
  List<int> _value1;
  int argument;
  _Survey({Key key, this.argument});
  int value0=0;
  List<File> _file;

  void choose(i) async {
    var file;
    file = await ImagePicker.pickImage(source: ImageSource.camera);
    // giving me error when i take a picture.NoSuchMethodError (NoSuchMethodError: The method '[]=' was called on null. Receiver: nullTried calling: []=(0, Instance of '_File'))
    setState(() => _file[i] = file);
  }
  //cond 1 i can't press the radio button
  void _setvalue1(int value, i) { 
    setState(() {
     _value1[i]=value; 
    });
    }
  // cond 2  doesn't work and giving me rangeerror invalid value
  // _setvalue1(int value, i) { 
  //   setState(() {
  //    _value1[i]=value; 
  //   });
  // } 

  Widget makeRadioTiles(data, index) {
    List<Widget> list = new List<Widget>();

    for (int i = 0; i < data.length; i++) {
      int id = data[i].answerID;
      list.add(new RadioListTile(
        value: id,
        groupValue: _value1,
        // cond1
        onChanged:(id) => _setvalue1(id, index),
        // cond 2
        // onChanged: _setvalue1(id, index), 
        activeColor: Colors.green,
        controlAffinity: ListTileControlAffinity.trailing,
        title: new Text('${data[i].answerName}'),
      ));
    }
    Column column = new Column(
      children: list,
    );
    return column;
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return BaseWidget<VesselScreenModel>(
        model: VesselScreenModel(api: Provider.of(context)),
        onModelReady: (model) => model.getQuestion(argument),
        builder: (context, model, child) => model.busy
            ? Center(child: new CircularProgressIndicator())
            : ListView.builder(
                padding: const EdgeInsets.all(32),
                scrollDirection: Axis.vertical,
                shrinkWrap: true,
                itemCount: model.questions.data.questions.length,
                itemBuilder: (context, i) {

                  //initialize your lists here 
                  _value1 = List<int>(i);
                  _file = List<File>(i);

                  var dataSnapshot = model.questions;
                  var snapshot = dataSnapshot.data.questions[i];
                  return Card(
                    color: Colors.white,
                    child: Column(
                      children: [
                        Center(
                          child: _file == null
                              ? Text('No image selected.')
                              : Image.file(_file[i]),
                        ),
                        ListTile(
                            title: Text('${snapshot.questionName}',
                                style: TextStyle(
                                    fontWeight: FontWeight.w900,
                                    color: Colors.black))),
                        Column(
                          children: <Widget>[
                            makeRadioTiles(snapshot.answers, i)
                          ],
                        ),
                        Container(
                          padding: const EdgeInsets.only(left: 16, right: 16),
                          child: TextField(
                            decoration: InputDecoration(labelText: 'Comment'),
                          ),
                        ),
                        Align(
                          alignment: Alignment.centerLeft,
                          child: Container(
                            child: FlatButton(
                                color: Color.fromRGBO(105, 114, 100, 0),
                                //where i take a picture for image
                                onPressed: () => choose(i),
                                child: const Text('Upload Image',
                                    style: TextStyle(fontSize: 15))),
                          ),
                        ),
                      ],
                    ),
                  );
                },
              ),
           );
  }
}