2

i know it's a bit messy, and I'm pretty new with flutter, I'd quite understand how state behaves on react, but state management on flutter seems doesn't behave the same way on array variable.

When I tried to setstate with a different approach, it gives me a different error message instead. I've been working on this particular widget for a week but still don't know where did I do wrong.


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))),
                          ),
                        ),
                      ],
                    ),
                  );
                },
              ));
  }
}

Ariel Malada
  • 21
  • 1
  • 3

1 Answers1

0

You are using a fixed size list _value1 and _file. Consider initializing the two lists with their sizes as soon as you know the upper bound for your array index.

I have modified your code slightly to make it work.


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))),
                          ),
                        ),
                      ],
                    ),
                  );
                },
              ),
           );
  }
}

Ashutosh Singh
  • 1,107
  • 17
  • 28