Flutter中的FutureBuilder和异步函数

时间:2020-03-12 20:38:59

标签: flutter

我在使用FutureBuilder时遇到问题,当有更改时(例如当我更改单选按钮的值时),它会刷新并再次执行代码,我单击单选按钮,它会重新加载似乎所有的futurebuilder。 编辑:我已经纠正了问题,这是我的解决方案,我不确定它是否一直有效

我的完整代码是:

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

// Create a Form widget.
class Affiche_grille extends StatefulWidget {
  @override
  _Affiche_grille_State createState() {
    return _Affiche_grille_State();
  }
}

// Create a corresponding State class.
// This class holds data related to the form.

class _Affiche_grille_State extends State<Affiche_grille> {
  @override
  final _formKey = GlobalKey<FormState>();
  List<String> radioValues = [];
  Future<List<Match>> grid;

  Future <List<Match>> Grille_display() async {
    // SERVER LOGIN API URL
    var url = 'http://www.axis-medias.fr/game_app/display_grid.php';

    // Store all data with Param Name.
    var data = {'id_grille': 1};

    // Starting Web API Call.
    var response = await http.post(url, body: json.encode(data));

    // Getting Server response into variable.

    var jsondata = json.decode(response.body);

    List<Match> Matchs = [];

    for (var u in jsondata) {
      Match match = Match(u["equipe1"],u["equipe2"],u["type_prono"]);
      Matchs.add(match);
      radioValues.add("N");
    }
    return Matchs;
  }

  void initState() {
    grid = Grille_display();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {

    final appTitle = 'MONEYFREE';

    return MaterialApp(
      title: appTitle,
      home: Scaffold(
        appBar: AppBar(
          title: Text(appTitle),
        ),
        body: Container(
          child:
            FutureBuilder(
              future: grid,
              builder: (BuildContext context, AsyncSnapshot snapshot) {
                if (snapshot.data == null) {
                  return Container (
                    child: Center(
                      child: Text("Chargement en cours...")
                    )
                  );
                }
                else {
                List<Match> values = snapshot.data;
                return Form(
                      key: _formKey,
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: <Widget>[
                          DataTable(
                            columnSpacing: 20,
                            columns: [
                              DataColumn(
                                label: Text("Libelle Match"),
                                numeric: false,
                                tooltip: "",
                              ),
                              DataColumn(
                                label: Text("1"),
                                numeric: false,
                                tooltip: "",
                              ),
                              DataColumn(
                                label: Text("N"),
                                numeric: false,
                                tooltip: "",
                              ),
                              DataColumn(
                                label: Text("2"),
                                numeric: false,
                                tooltip: "",
                              ),
                            ],
                            rows:
                            List.generate(values.length, (index) {
                              return DataRow(
                                  cells: [
                                    DataCell(
                                      Text(values[index].equipe1.toString() + " - " + values[index].equipe2.toString()),
                                    ),
                                    DataCell(
                                      Radio(
                                        value: "1",
                                        groupValue: radioValues[index],
                                        onChanged: (val) {
                                          setState(() {
                                            radioValues[index] = val;
                                            print('Change 1');
                                            print(radioValues);
                                          });
                                        },
                                      ),
                                    ),
                                    DataCell(
                                      Radio(
                                        value: "N",
                                        groupValue: radioValues[index],
                                        onChanged: (val) {
                                          setState(() {
                                            radioValues[index] = val;
                                            print('Change N');
                                            print(radioValues);
                                          });
                                        },
                                      ),
                                    ),
                                    DataCell(
                                      Radio(
                                        value: "2",
                                        groupValue: radioValues[index],
                                        onChanged: (val) {
                                          setState(() {
                                            radioValues[index] = val;
                                            print('Change 2');
                                            print(radioValues);
                                          });
                                        },
                                      ),
                                    ),
                                  ]
                              );
                            }).toList(),
                          ),
                          Center(
                            child: RaisedButton(
                              color: Colors.green,
                              textColor: Colors.white,
                              padding: EdgeInsets.fromLTRB(9, 9, 9, 9),
                              child: Text('VALIDER VOTRE GRILLE'),
                              onPressed: () {
                                Valide_grille();
                              },
                            ),
                          ),
                        ],
                      )
                  );
                };
                },
            ),
        ),
      ),
      );
  }

  Future Valide_grille() async{
    // For CircularProgressIndicator.
    bool visible = false ;
    // Showing CircularProgressIndicator.
    setState(() {
      visible = true ;
    });

    // SERVER LOGIN API URL
    var url = 'http://www.axis-medias.fr/game_app/valide_grid.php';

    var concatenate='';

    radioValues.forEach((item){
      concatenate=concatenate+item;
    });

    // Store all data with Param Name.
    var data = {'id_membre':1, 'id_grille':1,'result':concatenate};

    print (data);

    var grille_encode=jsonEncode(data);

    print(grille_encode);

    // Starting Web API Call.
    var response = await http.post(url, body: grille_encode);

    print(response.body);

    // Getting Server response into variable.
    var message = json.decode(response.body);

    // If the Response Message is Matched.
    if(message == 'OK')
    {
      print('VALIDATION DE LA GRILLE OK');
      // Hiding the CircularProgressIndicator.
      setState(() {
        visible = false;
      });

    }else{

      // If Email or Password did not Matched.
      // Hiding the CircularProgressIndicator.
      setState(() {
        visible = false;
      });

      // Showing Alert Dialog with Response JSON Message.
      showDialog(
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(
            title: new Text(message),
            actions: <Widget>[
              FlatButton(
                child: new Text("OK"),
                onPressed: () {
                  Navigator.of(context).pop();
                },
              ),
            ],
          );
        },
      );
    }
  }
  }

class Match {

  final String equipe1;
  final String equipe2;
  final String typeprono;

  const Match(this.equipe1, this.equipe2, this.typeprono);

}

1 个答案:

答案 0 :(得分:0)

您可以在下面复制粘贴运行完整代码

原因

每次发出重建文件时,都会调用状态为didUpdateWidget

FutureBuilder。此函数检查旧的旧对象是否与新的旧对象不同,如果有,则重新触发FutureBuilder

https://github.com/flutter/flutter/issues/11426#issuecomment-414047398

解决方案

Future _future;

@override
  void initState() {
    // TODO: implement initState
    _future = Grille_display();
  }
 ... 
 child: FutureBuilder(
            future: _future,  

工作演示

enter image description here

完整代码

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

// Create a Form widget.
class Affiche_grille extends StatefulWidget {
  @override
  _Affiche_grille_State createState() {
    return _Affiche_grille_State();
  }
}

// Create a corresponding State class.
// This class holds data related to the form.

class _Affiche_grille_State extends State<Affiche_grille> {
  @override
  final _formKey = GlobalKey<FormState>();
  List<String> radioValues = [];

  Future<List<Match>> Grille_display() async {
    // SERVER LOGIN API URL
    var url = 'http://www.axis-medias.fr/game_app/display_grid.php';

    // Store all data with Param Name.
    var data = {'id_grille': 1};

    // Starting Web API Call.
    var response = await http.post(url, body: json.encode(data));

    // Getting Server response into variable.

    var jsondata = json.decode(response.body);

    List<Match> Matchs = [];

    for (var u in jsondata) {
      Match match = Match(u["equipe1"], u["equipe2"], u["type_prono"]);
      Matchs.add(match);
    }
    return Matchs;
  }

  Future _future;

  @override
  void initState() {
    // TODO: implement initState
    _future = Grille_display();
  }

  @override
  Widget build(BuildContext context) {
    final appTitle = 'MONEYFREE';

    return MaterialApp(
      title: appTitle,
      home: Scaffold(
        appBar: AppBar(
          title: Text(appTitle),
        ),
        body: Container(
          child: FutureBuilder(
            future: _future,
            builder: (BuildContext context, AsyncSnapshot snapshot) {
              if (snapshot.data == null) {
                return Container(
                    child: Center(child: Text("Chargement en cours...")));
              } else {
                List<Match> values = snapshot.data;
                values.forEach((m) {
                  radioValues.add("N");
                  //like N or something
                });
                print('valeur radio après initialisation');
                print(radioValues);
                return Form(
                    key: _formKey,
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: <Widget>[
                        DataTable(
                          columnSpacing: 20,
                          columns: [
                            DataColumn(
                              label: Text("Libelle Match"),
                              numeric: false,
                              tooltip: "",
                            ),
                            DataColumn(
                              label: Text("1"),
                              numeric: false,
                              tooltip: "",
                            ),
                            DataColumn(
                              label: Text("N"),
                              numeric: false,
                              tooltip: "",
                            ),
                            DataColumn(
                              label: Text("2"),
                              numeric: false,
                              tooltip: "",
                            ),
                          ],
                          rows: List.generate(values.length, (index) {
                            return DataRow(cells: [
                              DataCell(
                                Text(values[index].equipe1.toString() +
                                    " - " +
                                    values[index].equipe2.toString()),
                              ),
                              DataCell(
                                Radio(
                                  value: "1",
                                  groupValue: radioValues[index],
                                  onChanged: (val) {
                                    setState(() {
                                      radioValues[index] = val;
                                      print('Change 1');
                                      print(radioValues);
                                    });
                                  },
                                ),
                              ),
                              DataCell(
                                Radio(
                                  value: "N",
                                  groupValue: radioValues[index],
                                  onChanged: (val) {
                                    setState(() {
                                      radioValues[index] = val;
                                      print(radioValues);
                                    });
                                  },
                                ),
                              ),
                              DataCell(
                                Radio(
                                  value: "2",
                                  groupValue: radioValues[index],
                                  onChanged: (val) {
                                    setState(() {
                                      radioValues[index] = val;
                                      print(radioValues);
                                    });
                                  },
                                ),
                              ),
                            ]);
                          }).toList(),
                        ),
                        Center(
                          child: RaisedButton(
                            color: Colors.green,
                            textColor: Colors.white,
                            padding: EdgeInsets.fromLTRB(9, 9, 9, 9),
                            child: Text('VALIDER VOTRE GRILLE'),
                            onPressed: () {
                              Valide_grille();
                            },
                          ),
                        ),
                      ],
                    ));
              }
              ;
            },
          ),
        ),
      ),
    );
  }

  Future Valide_grille() async {
    // For CircularProgressIndicator.
    bool visible = false;
    // Showing CircularProgressIndicator.
    setState(() {
      visible = true;
    });

    // SERVER LOGIN API URL
    var url = 'http://www.axis-medias.fr/game_app/valide_grid.php';

    // Store all data with Param Name.
    var data = jsonEncode(radioValues);

    print(radioValues);
    // Starting Web API Call.
    var response = await http.post(url, body: json.encode(data));

    // Getting Server response into variable.
    var message = json.decode(response.body);

    // If the Response Message is Matched.
    if (message == 'OK') {
      print('VALIDATION DE LA GRILLE OK');
      // Hiding the CircularProgressIndicator.
      setState(() {
        visible = false;
      });
    } else {
      // If Email or Password did not Matched.
      // Hiding the CircularProgressIndicator.
      setState(() {
        visible = false;
      });

      // Showing Alert Dialog with Response JSON Message.
      showDialog(
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(
            title: new Text(message),
            actions: <Widget>[
              FlatButton(
                child: new Text("OK"),
                onPressed: () {
                  Navigator.of(context).pop();
                },
              ),
            ],
          );
        },
      );
    }
  }
}

class Match {
  final String equipe1;
  final String equipe2;
  final String typeprono;

  const Match(this.equipe1, this.equipe2, this.typeprono);
}

void main() => runApp(MyApp());

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

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

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}