Stateful widget not initiating

Viewed 22

For context, this app consist on a form divided in different cards constructed automatically from a list which says how many questions per card we have and which are those questions. All this is being showed on screen from the provider, in which I have a map with all the answers. This is sent via API at the end of the form.

These questions have different types of answer. In this case the stateful widget which doesn't initiates is the radiobutton (as far as I know it can only be stateful).

How was the bug detected? Navigating into specific cards the answers of radio buttons appear but are not read from the provider because those fields in the form map of the answer still don't exist. What have I tried? I was printing a debug flag on the init method in the radio buttons. What was the result? Some cards seem to start correctly, and never give troubles, but some other cards only load the first radio button.

Additional info: it seems like the back button also causes some malfunctioning because when I answer these questions and go back they won't show the real value from the provider.

For some reference I leave some code, but it's really messy. I thank any kind of help, I'm not looking for the correct code, I just want to know where could the problem be or if anyone has ever been in this situation.

class CustomRadioButton extends StatefulWidget {
  final List<String> opcions;
  final Map map;
  final dynamic field;
  const CustomRadioButton({
    Key? key,
    required this.opcions,
    required this.map,
    required this.field,
  }) : super(key: key);

  @override
  State<CustomRadioButton> createState() => _CustomRadioButtonState();
}

class _CustomRadioButtonState extends State<CustomRadioButton> {
  String _opcio = '';

  @override
  void initState() {
    print('radio: ${widget.field}'); //this line doesn't always execute
    if (widget.field.length == 1) {
      _opcio = widget.map[widget.field[0]] != null
          ? widget.map[widget.field[0]] ==
                  'true' //es string, no booleano (20 min debugando)
              ? widget.opcions[0]
              : widget.opcions[1]
          : '';
    } else {
      _opcio = '';
      for (int i = 0; i < widget.field.length; i++) {
        //si true set opcio
        if (widget.map[widget.field[i]] == 'true') {
          _opcio = widget.opcions[i];
          break; //sortir del for
        }
      }
    }
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: widget.opcions
          .map((e) => RadioListTile(
              title: Text(e),
              value: e,
              groupValue: _opcio,
              onChanged: (String? val) {
                setState(() {
                  _opcio = val!;
                  print(_opcio);
                });
                if (widget.field.length == 1) {
                  if (val == widget.opcions[0]) {
                    widget.map[widget.field[0]] = 'true';
                  } else {
                    widget.map[widget.field[0]] = 'false';
                  }
                } else {
                  for (int i = 0; i < widget.field.length; i++) {
                    if (val == widget.opcions[i]) {
                      widget.map[widget.field[i]] = 'true';
                    } else {
                      widget.map[widget.field[i]] = 'false';
                    }
                  }
                }
              }))
          .toList(),
    );
  }
}

Methods to build the content of the card

Widget generarPreguntes() {
    final entretienProvider =
        Provider.of<EntretienProvider>(context, listen: false);
    List<Widget> llistatPreguntes = [];
    int preguntesPerCard =
        entretienProvider.preguntesPerCard[entretienProvider.card];
    //calcul de la pregunta que s'ha de mostrar
    int preguntaActual = 0;
    for (int tarja = entretienProvider.card - 1; tarja >= 0; tarja--) {
      preguntaActual =
          preguntaActual + entretienProvider.preguntesPerCard[tarja];
    }
    entretienProvider.pregunta = preguntaActual;
    //construccio de les preguntes
    for (int i = 0; i < preguntesPerCard; i++) {
      //afegir pregunta al llistat final
      llistatPreguntes.add(generarPregunta());
      //passar a la seguent pregunta
      entretienProvider.seguentPregunta();
      print('prg: ${entretienProvider.pregunta}');
    }
    return Column(children: llistatPreguntes);
  }

  //genera la pregunta actual
  Widget generarPregunta() {
    final entretienProvider =
        Provider.of<EntretienProvider>(context, listen: false);

    //accedir a la pregunta amb la pregunta actual
    Pregunta pregunta =
        entretienProvider.preguntesDeManteniment[entretienProvider.pregunta];
    List<Widget> widgetList = [];
    int i = 0;
    int picCounter = 0;
    //comptador de imatges dins d'una mateixa pregunta
    //afegir el titol de la pregunta al widget de la pregunta
    List<Widget> titolPregunta = [
      Flexible(
        child: Text((entretienProvider.pregunta + 1).toString() +
            '. ' +
            pregunta.titol),
      ),
    ];
    widgetList.add(
      Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: titolPregunta,
      ),
    );
    //iterem per cada camp de la resposta
    for (var camp in pregunta.camps) {
      String cas = camp.tipus;
      //seleccionem un dels tipus de resposta...
      switch (cas) {
        case 'checkList':
          //nomes s'utilitza en la imatge de les diferents seccions de l'escala
          widgetList.add(StackImage(entretienProvider: entretienProvider));
          break;
        case 'boolea':
          {
            //afegim la opcio booleana
            if (camp.descripcio == null) {
              titolPregunta.add(
                EntretienCheckBox(
                  title: camp.descripcio ?? '',
                  providerValue: entretienProvider
                              .fitxaMantenimentMap[pregunta.respostes[i]] ==
                          'true'
                      ? true
                      : false,
                  map: entretienProvider.fitxaMantenimentMap,
                  field: pregunta.respostes[i],
                ),
              );
            } else {
              widgetList.add(
                EntretienCheckBox(
                  title: camp.descripcio,
                  providerValue: entretienProvider
                              .fitxaMantenimentMap[pregunta.respostes[i]] ==
                          'true'
                      ? true
                      : false,
                  map: entretienProvider.fitxaMantenimentMap,
                  field: pregunta.respostes[i],
                ),
              );
            }
          }
          break;
        case 'text':
          {
            //afegim un textfield per resopndre amb text
            TextEditingController controller = TextEditingController();
            controller.text =
                entretienProvider.fitxaMantenimentMap[pregunta.respostes[i]] ??
                    '';
            widgetList.add(Padding(
              padding: const EdgeInsets.all(8.0),
              child: EntretienCommentInput(
                title: camp.descripcio!,
                hint: camp.descripcio!,
                controller: controller,
                field: pregunta.respostes[i],
                map: entretienProvider.fitxaMantenimentMap,
              ),
            ));
          }
          break;
        case 'number':
          {
            //afegim un textfield per respondre amb numeros
            TextEditingController controller = TextEditingController();
            controller.text = entretienProvider
                    .fitxaMantenimentMap[pregunta.respostes[i].toString()] ??
                '';
            widgetList.add(Padding(
              padding: const EdgeInsets.all(8.0),
              child: EntretienCommentInput(
                  title: camp.descripcio!,
                  hint: camp.descripcio!,
                  controller: controller,
                  field: pregunta.respostes[i],
                  map: entretienProvider.fitxaMantenimentMap,
                  obligatori: pregunta.campsObligatoris != null ? true : false,
                  inputKey: TextInputType.number),
            ));
          }
          break;
        case 'radioButton':
          {
            //afegim les opcions de radiobutton, nomes agafarem 1
            camp.descripcio != null
                ? widgetList.add(Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: Text(camp.descripcio!),
                  ))
                : widgetList.add(
                    const SizedBox(),
                  );
            print('radioButton selected');
            print(camp.opcions);
            print(pregunta.respostes[i]);
            widgetList.add(Padding(
              padding: const EdgeInsets.all(8.0),
              child: CustomRadio(
                opcions: camp.opcions!,
                field: pregunta.respostes[i],
                map: entretienProvider.fitxaMantenimentMap,
              ),
            ));
          }
          break;
        case 'fotos':
          {
            //afegim el boto de fotos
            picCounter++;
            widgetList.add(Padding(
              padding: const EdgeInsets.all(8.0),
              child: ElevatedButton(
                  onPressed: () {
                    Navigator.pushNamed(context, 'entretienImg',
                        arguments: [pregunta, picCounter]);
                  },
                  child: const Icon(Icons.camera_alt)),
            ));
            //no tenim en compte aquest camp ja que s'envia al final
            i--;
          }
          break;
      }
      i++;
    }
    return Column(
      children: widgetList,
    );
  }
}

Provider (constructing the questions from here)

Map<String, dynamic> _fitxaMantenimentMap = {};
  Map<String, dynamic> get fitxaMantenimentMap => _fitxaMantenimentMap;
  set fitxaMantenimentMap(Map<String, dynamic> value) {
    _fitxaMantenimentMap = value;
    notifyListeners();
  }
...
int _posicioFinal = 0;
  int get posicioFinal => _posicioFinal;

  set posicioFinal(int quantitatCards) {
    _posicioFinal = quantitatCards;
    notifyListeners();
  }

  int _card = 0;
  int get card => _card;
  set card(int card) {
    _card = card;
    notifyListeners();
  }

  int _pregunta = 0;
  int get pregunta => _pregunta;

  seguentPregunta() {
    _pregunta++;
  }

  set pregunta(int pregunta) {
    _pregunta = pregunta;
  }

  seguentCard() {
    _card++;
    notifyListeners();
  }

  anteriorCard() {
    _card--;
    pregunta = pregunta - (preguntesPerCard[card] + preguntesPerCard[card + 1]);
    notifyListeners();
  }
0 Answers
Related