TextField перезагружает FutureBuilder при нажатии / влево во флаттере - PullRequest
0 голосов
/ 27 мая 2019

Пользователь может либо ввести ответ с помощью InputChips, либо вручную ввести его в TextField.Когда я пытаюсь использовать InputChips, правильный ответ не определяется.Когда я пытаюсь ввести его вручную, FutureBuilder перезагружается, когда я вхожу и покидаю TextField.Какова причина?Функция Future должна вызываться только один раз, потому что она выбирает случайный документ из Firestore, разбивает строку и скремблирует разные части.Это какая-то форма викторины.

class _buildPhrases extends State<PhrasesSession>{
  TextEditingController _c;
  String _text = "initial";

  @override
  void initState(){
    _c = new TextEditingController();
    super.initState();
  }

  @override
  void dispose(){
    _c?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {

    final Arguments args = ModalRoute.of(context).settings.arguments;
    var height = MediaQuery.of(context).size.height;
    var width = MediaQuery.of(context).size.width;



    // TODO: implement build
    return Scaffold(
      body: Column(
        children: <Widget>[
          Flexible(flex: 2, child: _buildRest(context),),
          Flexible(flex: 5,
            child: FutureBuilder(
              future: getEverything(args.colName),
              builder: (context, snapshot){
                if(!snapshot.hasData){
                  return Center(child: CircularProgressIndicator(),);
                }else{

                  return Column(
                    children: <Widget>[
                      Flexible(flex: 1, child: Text(snapshot.data[1]),),
                      Divider(),
                      Flexible(flex: 2, child: Container(
                        child: TextField(
                        onChanged: (t){
                            _text += "$t ";
                            if(_c.text == snapshot.data[0]){
                              return print("CORRECT ANSWER");
                            }
                        },
                        controller: _c,
                        textAlign: TextAlign.center,
                          enabled: true,

                      ),
                      ),),
                      Flexible(flex: 3,
                        child: ListView.builder(
                          scrollDirection: Axis.horizontal,
                          itemCount: snapshot.data.length - 2,
                          itemBuilder: (context, index){
                            if(index>snapshot.data.length - 2){
                              return null;
                            }else{
                              return Padding(
                                padding: const EdgeInsets.all(4.0),
                                child: InputChip(
                                  label: Text(snapshot.data[index + 2]),
                                  onPressed: (){
                                    _c.text += "${snapshot.data[index  + 2]} ";
                                  },
                                ),
                              );
                            }
                          },
                        ))
                    ],
                  );
                }
              },
            ),)
        ],
      )
    );
  }
}

1 Ответ

1 голос
/ 28 мая 2019

Давайте решим это по частям.

Когда я пытаюсь ввести его вручную, FutureBuilder перезагружается, когда я вхожу и покидаю TextField.В чем причина?

Это происходит потому, что когда клавиатура показывает или скрывает структуру флаттера, вызывает метод build вашего виджета, и это поведение по умолчанию является причиной, по которой ваш FutureBuilder перезаписывается,Вам следует избегать вызова сетевых методов внутри build метода, и я советую вам использовать шаблон BLoC для обработки состояния вашего виджета.

Моему будущему нужна строка, которая передается из другого маршрута.Посмотрите аргументы args = .... Есть идеи, как я могу получить это в initState?

Ну, если вам нужен экземпляр context, чтобы получить этот String, вы не можете получить доступ к текущему контексту внутриinitState метод, потому что ваш виджет еще не полностью инициализирован.Простой способ решить эту проблему в вашем случае, но не лучший, это проверить, были ли данные уже получены из сети или нет.

Future _myNetworkFuture; // declare this as member of your stateWidgetClass

Widget build(BuildContext context){
   final Arguments args = ModalRoute.of(context).settings.arguments;
   var height = MediaQuery.of(context).size.height;
   var width = MediaQuery.of(context).size.width;

   // this line says if(_myNetworkFuture == null) do the thing.
   _myNetworkFuture ??= getEverything(args.colName);

   return ...
   Flexible(flex: 5,
        child: FutureBuilder(
          future: _myNetworkFuture,
          builder: (context, snapshot){ 
           // ...
          }
}

При таком подходе, когда среда флаттера вызывает метод build, если вы уже получилиданные вы не загружаете данные снова.Но я действительно советую вам использовать шаблон BLoC в такой ситуации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...