首页 > 解决方案 > 材质按钮未调用 post 方法功能

问题描述

我是 FLutter 的初学者,我有一个 json,我想通过颤振发送到互联网

这是我要发送的 json:

{
     "userid": 41,
    "name": "dhya",
    "price": 11,
    "players": [
        {
            "id":1,
            "firstname":"aa",
            "lastname":"ee",
            "position":"df",
            "price":12.1,
            "appearences":2,
            "goals":1,
            "assists":1,
            "cleansheets":1,
            "redcards":1,
            "yellowcards":1,
            "image":"qq"
            
        },
  {
            "id":2,
            "firstname":"aa",
            "lastname":"ee",
            "position":"df",
            "price":12.1,
            "appearences":2,
            "goals":1,
            "assists":1,
            "cleansheets":1,
            "redcards":1,
            "yellowcards":1,
            "image":"qq"
            
        }
    ]
     }

作为初学者,我不知道如何发送服务器将以我想要的 json 格式接收的对象,所以我使用了快速类型并创建了这个模型

// To parse this JSON data, do
//
//     final clubJson = clubJsonFromJson(jsonString);

import 'dart:convert';

ClubJson clubJsonFromJson(String str) => ClubJson.fromJson(json.decode(str));

String clubJsonToJson(ClubJson data) => json.encode(data.toJson());

class ClubJson {
  ClubJson({
    this.userid,
    this.name,
    this.price,
    this.players,
  });

  int userid;
  String name;
  int price;
  List<Player> players;

  factory ClubJson.fromJson(Map<String, dynamic> json) => ClubJson(
    userid: json["userid"],
    name: json["name"],
    price: json["price"],
    players: List<Player>.from(json["players"].map((x) => Player.fromJson(x))),
  );

  Map<String, dynamic> toJson() => {
    "userid": userid,
    "name": name,
    "price": price,
    "players": List<dynamic>.from(players.map((x) => x.toJson())),
  };
}

class Player {
  Player({
    this.id,
    this.firstname,
    this.lastname,
    this.position,
    this.price,
    this.appearences,
    this.goals,
    this.assists,
    this.cleansheets,
    this.redcards,
    this.yellowcards,
    this.image,
    this.clubid,
  });

  int id;
  String firstname;
  String lastname;
  String position;
  double price;
  int appearences;
  int goals;
  int assists;
  int cleansheets;
  int redcards;
  int yellowcards;
  String image;
  int clubid;

  factory Player.fromJson(Map<String, dynamic> json) => Player(
    id: json["id"],
    firstname: json["firstname"],
    lastname: json["lastname"],
    position: json["position"],
    price: json["price"].toDouble(),
    appearences: json["appearences"],
    goals: json["goals"],
    assists: json["assists"],
    cleansheets: json["cleansheets"],
    redcards: json["redcards"],
    yellowcards: json["yellowcards"],
    image: json["image"],
    clubid: json["clubid"],
  );

  Map<String, dynamic> toJson() => {
    "id": id,
    "firstname": firstname,
    "lastname": lastname,
    "position": position,
    "price": price,
    "appearences": appearences,
    "goals": goals,
    "assists": assists,
    "cleansheets": cleansheets,
    "redcards": redcards,
    "yellowcards": yellowcards,
    "image": image,
    "clubid": clubid,
  };
}

现在最后剩下的步骤就是我在 FLutter 中编写的函数:

Future <void> PostRequest() async {
// set up POST request arguments
    final url = Uri.parse('http://localhost:3000/api/questions/addQuestion');
    Map<String, String> headers = {"Content-type": "application/json"};
    ClubJson club = ClubJson(userid: 1, name: "dsds", price: 55.2,players: null );
    for(var item in widget.selectedPlayers){
      club.players.add(Player(id:item.playerID,firstname:item.firstName,lastname:item.lastName,position:item.position,price:item.price,appearences:item.appearances,goals:item.goals,assists:item.assists,cleansheets:item.cleanSheets,redcards:item.redCards,yellowcards:item.yellowCards,image:item.image));
    }

    String json = club.toJson().toString();
    print(club);
    // make POST request
    Response response = await post(url, headers: headers, body: json);
    // check the status code for the result
    int statusCode = response.statusCode;
    // this API passes back the id of the new item added to the body
    String body = response.body;

  }

在我单击按钮调用函数 PostRequest() 并将对象发送到互联网后,我收到一条奇怪的消息,并且调用没有完成:

======== Exception caught by gesture ===============================================================
The following assertion was thrown while handling a gesture:
Scaffold.of() called with a context that does not contain a Scaffold.

No Scaffold ancestor could be found starting from the context that was passed to Scaffold.of(). This usually happens when the context provided is from the same StatefulWidget as that whose build function actually creates the Scaffold widget being sought.

There are several ways to avoid this problem. The simplest is to use a Builder to get a context that is "under" the Scaffold. For an example of this, please see the documentation for Scaffold.of():
  https://api.flutter.dev/flutter/material/Scaffold/of.html
A more efficient solution is to split your build function into several widgets. This introduces a new context from which you can obtain the Scaffold. In this solution, you would have an outer widget that creates the Scaffold populated by instances of your new inner widgets, and then in these inner widgets you would use Scaffold.of().
A less elegant but more expedient solution is assign a GlobalKey to the Scaffold, then use the key.currentState property to obtain the ScaffoldState rather than using the Scaffold.of() function.

The context used was: CreateTeamView
  state: _CreateTeamViewState#c4658
When the exception was thrown, this was the stack: 
#0      Scaffold.of (package:flutter/src/material/scaffold.dart:1472:5)
#1      _CreateTeamViewState.build.<anonymous closure> (package:footyappp/Fantazyy/create_team_view.dart:325:36)
#2      _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:993:19)
#3      _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:1111:38)
#4      GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:183:24)
...
Handler: "onTap"
Recognizer: TapGestureRecognizer#eeb07
  debugOwner: GestureDetector
  state: possible
  won arena
  finalPosition: Offset(187.1, 658.5)
  finalLocalPosition: Offset(187.1, 25.1)
  button: 1
  sent tap down
====================================================================================================

这里是 Flutter 的完整代码:

import 'package:flutter/material.dart';
import 'package:footyappp/Fantazyy/club_json.dart';
import 'package:footyappp/Fantazyy/controller.dart';
import 'package:footyappp/Fantazyy/styles.dart';
import 'package:footyappp/Fantazyy/player%20copy.dart';
import 'package:footyappp/Fantazyy/players_creation_details_view.dart';
import 'package:http/http.dart';


class CreateTeamView extends StatefulWidget {

   List<Playerr> selectedPlayers;

  CreateTeamView({
    Key key,
    players,
    selectedPlayers,
  })  : selectedPlayers = (selectedPlayers == null) ? new List<Playerr>.generate(16, (int index) => null) : selectedPlayers;

  @override
  _CreateTeamViewState createState() => _CreateTeamViewState();


}




class _CreateTeamViewState extends State<CreateTeamView> {

   Future <void> PostRequest() async {
// set up POST request arguments
    final url = Uri.parse('http://localhost:3000/api/questions/addQuestion');
    Map<String, String> headers = {"Content-type": "application/json"};
    ClubJson club = ClubJson(userid: 1, name: "dsds", price: 55.2,players: null );
    for(var item in widget.selectedPlayers){
      club.players.add(Player(id:item.playerID,firstname:item.firstName,lastname:item.lastName,position:item.position,price:item.price,appearences:item.appearances,goals:item.goals,assists:item.assists,cleansheets:item.cleanSheets,redcards:item.redCards,yellowcards:item.yellowCards,image:item.image));
    }

    String json = club.toJson().toString();
    print(club);
    // make POST request
    Response response = await post(url, headers: headers, body: json);
    // check the status code for the result
    int statusCode = response.statusCode;
    // this API passes back the id of the new item added to the body
    String body = response.body;

  }

  final double _checkboxHeight = 30.0;
  double _startingBudget = 107.0;
  double _budget = 107.0;
  bool _everyTeam = false, _minThreeFreshers = false, _maxThreeSameTeam = true, _isTeamNameLong = false, _buttonEnabled = true;
  String _teamName = "";
  Widget _saveChanges = Text("Press to save changes");

  @override
  void initState() {
    Map<int,int> teamCount = new Map<int, int>();
    int fresherCount = 0;
    for (Playerr player in widget.selectedPlayers) {
        if (player != null) {
          _budget -= player.price;
         /* if (teamCount[player.club] == null) {
            teamCount[player.teams] = 1;
          } else {
            teamCount[player.teams]++;
            if (teamCount[player.club] > 3) _maxThreeSameTeam = false;
          }*/
        }
      }
    _minThreeFreshers = (fresherCount >= 3);
    _everyTeam = (teamCount.length >=7);
    super.initState();
  }

  emptyPlayer(int index) {
    Playerr player = widget.selectedPlayers[index];
    Widget playerView;

    if (player == null) {
      playerView = Image.asset("Assets/shirt_blank.png", fit: BoxFit.fitHeight,);
    } else {
      playerView = Column(
        children: <Widget>[
          Expanded(
            child: Image.asset(player.image, fit: BoxFit.fitHeight,),
          ),
          Container(
            color: Colors.green,
            child: Text(player.firstName.substring(0,1) + ". " + player.lastName, textAlign: TextAlign.center, softWrap: false, overflow: TextOverflow.fade,),
          ),
          Container(
            color: Colors.green,
            child: Text("£${player.price}m", textAlign: TextAlign.center),
          ),
        ],
      );
    }

    return Expanded(
      child: InkWell(
        onTap: () => Navigator.pushReplacement(context, MaterialPageRoute(builder: (BuildContext context) {return PlayersCreationDetailsView(selectedPlayers: widget.selectedPlayers, playerIndex: index,);})),
        child: Padding(padding: EdgeInsets.only(left: 3.0, right: 3.0), child:playerView,)
      ),
    );
  }

  @override
  Widget build(BuildContext context) {

    return WillPopScope(
      onWillPop: () async => false,
      child: Scaffold(
        appBar: AppBar(title: Text("Create your team"),),
        body: Stack(
            children: <Widget>[
              Column(
                mainAxisAlignment: MainAxisAlignment.start,
                children: <Widget>[
                  Expanded(
                      child: Stack(
                          children: <Widget>[
                            Positioned.fill(
                                child: Image.asset("Assets/pitch.jpg", fit: BoxFit.fitWidth, alignment: Alignment.topLeft,)
                            )
                          ]
                      )
                  ),
                ],
              ),
              Column( //players
                mainAxisAlignment: MainAxisAlignment.start,
                children: <Widget>[
                  Expanded(
                      flex: 1,
                      child: Container()
                  ),
                  Expanded(
                      flex: 6,
                      child:  Padding(
                        padding: EdgeInsets.only(left: 40.0, right: 40.0), child: Row(
                        mainAxisAlignment: MainAxisAlignment.spaceAround,
                        children: List.generate(2, (index) => emptyPlayer(index)),
                        ),
                      )
                  ),
                  Expanded(
                      flex: 1,
                      child: Container()
                  ),
                  Expanded(
                      flex: 6,
                      child:  Row(
                        mainAxisAlignment: MainAxisAlignment.spaceAround,
                        children: List.generate(5, (index) =>  emptyPlayer(index+2)),
                      )
                  ),
                  Expanded(
                      flex: 1,
                      child: Container()
                  ),
                  Expanded(
                      flex: 6,
                      child:  Row(
                        mainAxisAlignment: MainAxisAlignment.spaceAround,
                        children: List.generate(5, (index) =>  emptyPlayer(index+7)),
                      )
                  ),
                  Expanded(
                      flex: 1,
                      child: Container()
                  ),
                  Expanded(
                      flex: 6,
                      child:  Row(
                        mainAxisAlignment: MainAxisAlignment.spaceAround,
                        children: List.generate(4, (index) =>  emptyPlayer(index+12)),
                      )
                  ),
                  Expanded(
                      flex: 1,
                      child: Container()
                  ),
                  Container(
                    color: Styles.colorAccentDark,
                    padding: EdgeInsets.only(left: 8.0, right: 8.0),
                    child: Column(
                      children: <Widget>[
                        Padding(
                          padding: EdgeInsets.only(top: 4.0, bottom: 4.0),
                          child: Row(
                            children: <Widget>[
                              Expanded(
                                child: Text("Remaining Budget", style: Styles.budgetLabel,),
                              ),
                              Text("£${_budget}m", style: Styles.budgetLabel,)
                            ],
                          ),
                        ),
                        Row(
                          children: <Widget>[
                            Expanded(
                              child: Text("At least one player from every team:", style: Styles.checkboxLabel),
                            ),
                            Container(
                              height: _checkboxHeight,
                              child: Checkbox(
                                value: _everyTeam,
                                onChanged: (bool) => null,
                              ),
                            )
                          ],
                        ),
                        Row(
                          children: <Widget>[
                            Expanded(
                              child: Text("At least two freshers:", style: Styles.checkboxLabel),
                            ),
                            Container(
                              height: _checkboxHeight,
                              child: Checkbox(
                                value: _minThreeFreshers,
                                onChanged: (bool) => null,
                              ),
                            )
                          ],
                        ),
                        Row(
                          children: <Widget>[
                            Expanded(
                              child: Text("Max three players from same team:", style: Styles.checkboxLabel),
                            ),
                            Container(
                              height: _checkboxHeight,
                              child: Checkbox(
                                value: _maxThreeSameTeam,
                                onChanged: (bool) => null,
                              ),
                            )
                          ],
                        ),
                        Padding(
                          padding: EdgeInsets.only(bottom: 4.0),
                          child: Row(
                            children: <Widget>[
                              Expanded(
                                  child: TextField(
                                    onChanged: (string) {
                                      if (string.length >= 4) {
                                        _teamName = string;
                                        setState(() {
                                          _isTeamNameLong = true;
                                        });
                                      } else {
                                        setState(() {
                                          _isTeamNameLong = false;
                                        });
                                      }
                                    },
                                    decoration: InputDecoration(
                                      fillColor: Styles.colorBackgroundLight,
                                      filled: true,
                                      hintText: "Team Name",
                                    ),
                                  )
                              ),
                              Container(
                                height: _checkboxHeight,
                                child: Checkbox(
                                  value: _isTeamNameLong,
                                  onChanged: (bool) => null,
                                ),
                              )
                            ],
                          ),
                        )
                      ],
                    ),
                  )
                  ,
                  new MaterialButton(

                    height: 50.0,
                    minWidth: double.infinity,
                    color: Styles.colorButton,
                    splashColor: Colors.teal,
                    textColor: Colors.white,
                    child: _saveChanges,
                    onPressed: () {
                      if (_buttonEnabled) {
                        String message = "";

                        if (!_everyTeam) {
                          message +=
                          "You need at least one player from every team \n";
                        }
                        if (!_minThreeFreshers) {
                          message +=
                          "You need at least 3 freshers in your team \n";
                        }
                        if (!_maxThreeSameTeam) {
                          message +=
                          "You can have at most 3 players from the same team \n";
                        }
                        if (!_isTeamNameLong) {
                          message +=
                          "Your team name must be at least 4 characters long \n";
                        }
                        if (_budget < 0) {
                          message += "You can't exceed the budget \n";
                        }

                        if (message != "") {
                          final snackBar = SnackBar(
                              content: Text(message),
                              duration: Duration(seconds: 2)
                          );
                          Scaffold.of(context).showSnackBar(snackBar);

                          setState(() {
                            _saveChanges = FutureBuilder(

                              future: PostRequest(),
                              builder: (context, snapshot) {
                                if (snapshot.connectionState ==
                                    ConnectionState.done) {
                                  _buttonEnabled = true;
                                  return Text("Press to save changes");
                                }
                                // By default, show a loading spinner and disable button
                                _buttonEnabled = false;
                                return CircularProgressIndicator();
                              },
                            );
                          });                        }
                      }
                    }
                  ),

                ],
              ),
            ],
        )
      )
    );
  }

}

标签: flutterdart

解决方案


尝试像这样为脚手架小部件添加一个密钥

final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey();

 Scaffold(
      key: scaffoldKey,
      body:....

scaffoldKey.currentState.showSnackBar(snackBar);

或者如果您使用的是颤振 2,请使用它来显示 SnackBar

ScaffoldMessenger.of(context).showSnackBar(snackBar)

推荐阅读