【问题标题】:Flutter get snapshot.data[1] in future builderFlutter 在未来的 builder 中获取 snapshot.data[1]
【发布时间】:2020-10-23 01:23:31
【问题描述】:

我有以下代码

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter_form_builder/flutter_form_builder.dart';

class MyData {
  String title;
  String days;
  String words;
  String rep;
  String gender;
  var username;

  MyData({this.gender, this.title, this.days, this.words, this.rep, this.username,
  });

}

class StepperBody extends StatefulWidget {
  @override
  _StepperBodyState createState() => _StepperBodyState();
}

class _StepperBodyState extends State<StepperBody> {
  int currStep = 0;
  static var _focusNode = FocusNode();
  GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  final GlobalKey<FormBuilderState> _fbKey = GlobalKey<FormBuilderState>();
  Future<List<String>> _future;
  Future<List<String>> _car;

  List<GlobalKey<FormState>> formKeys = [
    GlobalKey<FormState>(),
    GlobalKey<FormState>(),
    GlobalKey<FormState>(),
    GlobalKey<FormState>()
  ];

  String _key = "786465659081B207EB5BF1EF9AF7552A6";
  String _api = "https://10.0.2.2/api/";

  Future<void> senddata(List<String> username) async {
    final response = await http.post(
        _api + "insert_data.php?key=" + _key, body: {
      "username": username,
    });
    var resp = jsonDecode(response.body);
    print(resp.toString());
  }

  Future<List<String>> getData() async {
    var url = _api + "get_data.php?key=" + _key;
    http.Response response = await http.get(url);
    var resp = jsonDecode(response.body);
    print(resp.toString());
    return resp.map<String>((m) => m['username'] as String).toList();
  }

  Future<List<String>> getCar() async {
    var url = _api + "get_car.php?key=" + _key;
    http.Response response = await http.get(url);
    var resp = jsonDecode(response.body);
    print(resp.toString());
    return resp.map<String>((m) => m['plate'] as String).toList();
  }

  @override
  void initState() {
    super.initState();

    _future = getData();
    _car = getCar();

    _focusNode.addListener(() {
      setState(() {});
      print('Has focus: $_focusNode.hasFocus');
    });
  }


  @override
  Widget build(BuildContext context) {
    void showSnackBarMessage(String message,
        [MaterialColor color = Colors.red]) {
      Scaffold.of(context).showSnackBar(SnackBar(content: Text(message)));
    }

    void _submitDetails(List<String> username) {
      final FormState formState = _formKey.currentState;
      final FormBuilderState fbKeyState = _fbKey.currentState;
/*
      _fbKey.currentState.save();
      if (_fbKey.currentState.validate()) {
        print(_fbKey.currentState.value);
      }

 */
      if (!fbKeyState.validate()) {
        showSnackBarMessage('Please enter correct data');
        senddata(username);

      } else {
        showSnackBarMessage('Saved');
        formState.save();
        senddata(username);
        print("Name: $username");



        _fbKey.currentState.save();
        if (_fbKey.currentState.validate()) {
          print(_fbKey.currentState.value);
        }
      }
    }

    return FutureBuilder<List<String>>(
        future: Future.wait([_future, _car]),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            final steps = [
              Step(
                title: const Text('Users'),
                //subtitle: const Text('Subtitle'),
                isActive: true,
                //state: StepState.editing,
                state: StepState.indexed,
                content: Form(
                  key: formKeys[0],
                  child: Column(
                    children: <Widget>[
                      FormBuilder(
                        key: _fbKey,
                        autovalidate: true,
                        child: FormBuilderCheckboxList(
                          decoration:
                          InputDecoration(labelText: "Languages you know"),
                          attribute: "languages",
                          initialValue: ["English"],
                          options: snapshot.data[0]
                              .map((languages) => FormBuilderFieldOption(
                              value: languages, child: Text("$languages")))
                              .toList(),
                        ),
                      ),
                    ],
                  ),
                ),
              ),
              Step(
                title: const Text('Users'),
                //subtitle: const Text('Subtitle'),
                isActive: true,
                //state: StepState.editing,
                state: StepState.indexed,
                content: Form(
                  key: formKeys[1],
                  child: Column(
                    children: <Widget>[
                      FormBuilder(
                        key: _fbKey,
                        autovalidate: true,
                        child: FormBuilderCheckboxList(
                          decoration:
                          InputDecoration(labelText: "Cars"),
                          attribute: "cars",
                          initialValue: ["BM-WD01"],
                          options: snapshot.data[1]
                              .map((car) => FormBuilderFieldOption(
                              value: car, child: Text("$car")))
                              .toList(),
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ];

            return Container(
                child: Form(
                  key: _formKey,
                  child: ListView(children: <Widget>[
                    Stepper(
                      steps: steps,
                      physics: ClampingScrollPhysics(),
                      type: StepperType.vertical,
                      currentStep: this.currStep,
                      onStepContinue: () {
                        setState(() {
                          if (formKeys[currStep].currentState.validate()) {
                            if (currStep < steps.length - 1) {
                              currStep = currStep + 1;
                            } else {
                              currStep = 0;
                            }
                          }
                          // else {
                          // Scaffold
                          //     .of(context)
                          //     .showSnackBar( SnackBar(content:  Text('$currStep')));

                          // if (currStep == 1) {
                          //   print('First Step');
                          //   print('object' + FocusScope.of(context).toStringDeep());
                          // }

                          // }
                        });
                      },
                      controlsBuilder: (BuildContext context,
                          {VoidCallback onStepContinue, VoidCallback onStepCancel}) {
                        return Row(
                          //   mainAxisAlignment: MainAxisAlignment.spaceBetween,
                          children: <Widget>[
                            //
                            RaisedButton(
                              color: Colors.red,
                              child: Text("Forward",
                                  style: TextStyle(color: Colors.white)),
                              onPressed: onStepContinue,
                            ),

                            SizedBox(width: 15,),
                            RaisedButton(
                              color: Colors.red,
                              child: Text(
                                  "Back", style: TextStyle(color: Colors.white)),
                              onPressed: onStepCancel,
                            ),
                          ],
                        );
                      },
                      onStepCancel: () {
                        setState(() {
                          if (currStep > 0) {
                            currStep = currStep - 1;
                          } else {
                            currStep = 0;
                          }
                        });
                      },
                      onStepTapped: (step) {
                        setState(() {
                          currStep = step;
                        });
                      },
                    ),

                    RaisedButton(
                      child: Text(
                        'Save',
                        style: TextStyle(color: Colors.white),
                      ),
                      onPressed: () {
                        var submitDetails = _submitDetails;
                        submitDetails(snapshot.data);
                      },
                      color: Colors.lightGreen,
                    ),
                  ]),
                ));
          } else {
            return CircularProgressIndicator();
          }
        }
    );
  }
}

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: "test",),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  MyAppScreenMode createState() => MyAppScreenMode();
}

class MyAppScreenMode extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {

    return new MaterialApp(
        theme: new ThemeData(
          primarySwatch: Colors.red,
        ),
        home: new Scaffold(

          appBar: new AppBar(
            title: new Text('Test stepper'),
          ),
          body: new StepperBody(),

        ));
  }
}

我想显示来自 mySQL 的多个列表,第一个函数 _future 工作正常,但是当我将 future: _future 替换为

future: Future.wait([_future, _car]),

我得到一个

元素类型“Future”不能分配给列表 输入“未来”

我尝试了许多其他解决方案,但没有一个可以使用 snapshot.data[0]、snapshot.data1 等来显示来自不同表的更多查询和数据。

无法与更多的未来建设者合作,这对于自己的每一步来说都会更容易,但后来我明白了

      Step(
        title: const Text('Users'),
        //subtitle: const Text('Subtitle'),
        isActive: true,
        //state: StepState.editing,
        state: StepState.indexed,
        content: Form(
          key: formKeys[0],
          child:  FutureBuilder<List>(
            future: _future,
              // ignore: missing_return
            builder: (BuildContext context, snapshot) {
              if (snapshot.connectionState == ConnectionState.done) {
                Column(
                  children: <Widget>[
                    FormBuilder(
                      key: _fbKey,
                      autovalidate: true,
                      child: FormBuilderCheckboxList(
                        decoration:
                        InputDecoration(
                            labelText: "Languages you know"),
                        attribute: "languages",
                        initialValue: ["English"],

                        options: snapshot.data
                            .map((gender) =>
                            FormBuilderFieldOption(
                                value: gender, child: Text("$gender")))
                            .toList(),


                      ),
                    ),
                  ],
                );
              }
            }
        ),
        ),
      ),
    ];

任何帮助将不胜感激。

【问题讨论】:

    标签: mysql dart


    【解决方案1】:

    问题的有效解决方案。如果有更好的方法欢迎留言:)

    import 'package:flutter/material.dart';
    import 'package:flutter/rendering.dart';
    import 'dart:async';
    import 'dart:convert';
    import 'package:http/http.dart' as http;
    import 'package:flutter_form_builder/flutter_form_builder.dart';
    
    class MyData {
      String title;
      String days;
      String words;
      String rep;
      String gender;
      var username;
    
      MyData(
          {this.gender, this.title, this.days, this.words, this.rep, this.username,
          });
    
    }
    
    class StepperBody extends StatefulWidget {
      @override
      _StepperBodyState createState() => _StepperBodyState();
    }
    
    class _StepperBodyState extends State<StepperBody> {
      int currStep = 0;
      static var _focusNode = FocusNode();
      GlobalKey<FormState> _formKey = GlobalKey<FormState>();
      final GlobalKey<FormBuilderState> _fbKey = GlobalKey<FormBuilderState>();
      Future<List<String>> _future;
      Future<List<String>> _getcar;
    
      List<GlobalKey<FormState>> formKeys = [
        GlobalKey<FormState>(),
        GlobalKey<FormState>(),
        GlobalKey<FormState>(),
        GlobalKey<FormState>()
      ];
    
      String _key = "786465659081B207EB5BF1EF9AF7552A6";
      String _api = "https://10.0.2.2/api/";
    
      Future<void> senddata() async {
        final response = await http.post(
            _api + "insert_data.php?key=" + _key, body: {
        });
        var resp = jsonDecode(response.body);
        print(resp.toString());
      }
    
      Future<List<String>> getData() async {
        var url = _api + "get_data.php?key=" + _key;
        http.Response response = await http.get(url);
        var resp = jsonDecode(response.body);
        print(resp.toString());
        return resp.map<String>((m) => m['username'] as String).toList();
      }
    
      Future<List<String>> getCar() async {
        var url = _api + "get_car.php?key=" + _key;
        http.Response response = await http.get(url);
        var resp = jsonDecode(response.body);
        print(resp.toString());
        return resp.map<String>((m) => m['plate'] as String).toList();
      }
    
    
      Widget getdis2(BuildContext context) {
        return FutureBuilder<List<String>>(
          future: _getcar, // a previously-obtained Future<String> or null
          builder: (BuildContext context, AsyncSnapshot<List<String>> snapshot) {
            List<Widget> children;
            if (snapshot.hasData) {
              children = <Widget>[
                FormBuilderCheckboxList(
                  decoration:
                  InputDecoration(
                      labelText: "Languages you know"),
                  attribute: "languages",
                  initialValue: ["English"],
                  options: snapshot.data
                      .map((gender) =>
                      FormBuilderFieldOption(
                          value: gender, child: Text("$gender")))
                      .toList(),
                ),
              ];
            } else if (snapshot.hasError) {
              children = <Widget>[
                Icon(
                  Icons.error_outline,
                  color: Colors.red,
                  size: 60,
                ),
                Padding(
                  padding: const EdgeInsets.only(top: 16),
                  child: Text('Error: ${snapshot.error}'),
                )
              ];
            } else {
              children = <Widget>[
                SizedBox(
                  child: CircularProgressIndicator(),
                  width: 60,
                  height: 60,
                ),
                const Padding(
                  padding: EdgeInsets.only(top: 16),
                  child: Text('Awaiting result...'),
                )
              ];
            }
            return Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: children,
              ),
            );
          },
        );
    
      }
    
      Widget getdis(BuildContext context) {
        return FutureBuilder<List<String>>(
            future: _future, // a previously-obtained Future<String> or null
            builder: (BuildContext context, AsyncSnapshot<List<String>> snapshot) {
              List<Widget> children;
              if (snapshot.hasData) {
                children = <Widget>[
                  FormBuilderCheckboxList(
                    decoration:
                    InputDecoration(
                        labelText: "Languages you know"),
                    attribute: "languages",
                    initialValue: ["English"],
                    options: snapshot.data
                        .map((gender) =>
                        FormBuilderFieldOption(
                            value: gender, child: Text("$gender")))
                        .toList(),
                  ),
                ];
              } else if (snapshot.hasError) {
                children = <Widget>[
                  Icon(
                    Icons.error_outline,
                    color: Colors.red,
                    size: 60,
                  ),
                  Padding(
                    padding: const EdgeInsets.only(top: 16),
                    child: Text('Error: ${snapshot.error}'),
                  )
                ];
              } else {
                children = <Widget>[
                  SizedBox(
                    child: CircularProgressIndicator(),
                    width: 60,
                    height: 60,
                  ),
                  const Padding(
                    padding: EdgeInsets.only(top: 16),
                    child: Text('Awaiting result...'),
                  )
                ];
              }
              return Center(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: children,
                ),
              );
            },
          );
    
      }
    
      @override
      void initState() {
        super.initState();
        _future = getData();
        _getcar = getCar();
    
        _focusNode.addListener(() {
          setState(() {});
          print('Has focus: $_focusNode.hasFocus');
        });
      }
    
    
      @override
      Widget build(BuildContext context) {
        void showSnackBarMessage(String message,
            [MaterialColor color = Colors.red]) {
          Scaffold.of(context).showSnackBar(SnackBar(content: Text(message)));
        }
    
        void _submitDetails() {
          final FormState formState = _formKey.currentState;
          final FormBuilderState fbKeyState = _fbKey.currentState;
    /*
          _fbKey.currentState.save();
          if (_fbKey.currentState.validate()) {
            print(_fbKey.currentState.value);
          }
    
     */
          if (!fbKeyState.validate()) {
            showSnackBarMessage('Please enter correct data');
            senddata();
          } else {
            showSnackBarMessage('Saved');
            formState.save();
            senddata();
            print("Name: ");
    
    
            _fbKey.currentState.save();
            if (_fbKey.currentState.validate()) {
              print(_fbKey.currentState.value);
            }
          }
        }
    
    
        final steps = [
          Step(
            title: const Text('Users'),
            //subtitle: const Text('Subtitle'),
            isActive: true,
            //state: StepState.editing,
            state: StepState.indexed,
            content: Form(
              key: formKeys[0],
              child: getdis(context),
            ),
          ),
          Step(
            title: const Text('Cars'),
            //subtitle: const Text('Subtitle'),
            isActive: true,
            //state: StepState.editing,
            state: StepState.indexed,
            content: Form(
              key: formKeys[1],
              child: getdis2(context),
            ),
          ),
        ];
    
        return Container(
            child: Form(
              key: _formKey,
              child: ListView(children: <Widget>[
                Stepper(
                  steps: steps,
                  physics: ClampingScrollPhysics(),
                  type: StepperType.vertical,
                  currentStep: this.currStep,
                  onStepContinue: () {
                    setState(() {
                      if (formKeys[currStep].currentState.validate()) {
                        if (currStep < steps.length - 1) {
                          currStep = currStep + 1;
                        } else {
                          currStep = 0;
                        }
                      }
                      // else {
                      // Scaffold
                      //     .of(context)
                      //     .showSnackBar( SnackBar(content:  Text('$currStep')));
    
                      // if (currStep == 1) {
                      //   print('First Step');
                      //   print('object' + FocusScope.of(context).toStringDeep());
                      // }
    
                      // }
                    });
                  },
                  controlsBuilder: (BuildContext context,
                      {VoidCallback onStepContinue, VoidCallback onStepCancel}) {
                    return Row(
                      //   mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: <Widget>[
                        //
                        RaisedButton(
                          color: Colors.red,
                          child: Text("Forward",
                              style: TextStyle(color: Colors.white)),
                          onPressed: onStepContinue,
                        ),
    
                        SizedBox(width: 15,),
                        RaisedButton(
                          color: Colors.red,
                          child: Text(
                              "Back", style: TextStyle(color: Colors.white)),
                          onPressed: onStepCancel,
                        ),
                      ],
                    );
                  },
                  onStepCancel: () {
                    setState(() {
                      if (currStep > 0) {
                        currStep = currStep - 1;
                      } else {
                        currStep = 0;
                      }
                    });
                  },
                  onStepTapped: (step) {
                    setState(() {
                      currStep = step;
                    });
                  },
                ),
    
                RaisedButton(
                  child: Text(
                    'Save',
                    style: TextStyle(color: Colors.white),
                  ),
                  onPressed: () {
                    var submitDetails = _submitDetails;
                    submitDetails();
                  },
                  color: Colors.lightGreen,
                ),
              ]),
            ));
      }
    }
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(title: "test",),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
    
      final String title;
    
      @override
      MyAppScreenMode createState() => MyAppScreenMode();
    }
    
    class MyAppScreenMode extends State<MyHomePage> {
      @override
      Widget build(BuildContext context) {
        return new MaterialApp(
            theme: new ThemeData(
              primarySwatch: Colors.red,
            ),
            home: new Scaffold(
    
              appBar: new AppBar(
                title: new Text('Test stepper'),
              ),
              body: new StepperBody(),
    
            ));
      }
    }
    

    【讨论】:

      【解决方案2】:

      对此我不确定,但据我了解,FutureBuilder 预计只有 1 个未来。这个未来的返回值可以通过“snapshot.data”访问。

      如果您需要等待多个 Future 解决,我建议您使用多个 FutureBuilder。

      另一种方法是在其他地方使用 Future.wait() 并从那里返回所有需要的数据作为一个 Furure。

      【讨论】:

      猜你喜欢
      • 2021-06-08
      • 2020-07-01
      • 2020-08-02
      • 2021-10-08
      • 2021-02-26
      • 1970-01-01
      • 1970-01-01
      • 2021-08-23
      • 2020-10-08
      相关资源
      最近更新 更多