flutter - 材质按钮未调用 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();
},
);
}); }
}
}
),
],
),
],
)
)
);
}
}
解决方案
尝试像这样为脚手架小部件添加一个密钥
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey();
Scaffold(
key: scaffoldKey,
body:....
scaffoldKey.currentState.showSnackBar(snackBar);
或者如果您使用的是颤振 2,请使用它来显示 SnackBar
ScaffoldMessenger.of(context).showSnackBar(snackBar)
推荐阅读
- python - pyspark 聚合,同时找到组的第一个值
- azure-devops - Azure 板,当用户故事导出使用 html 标记创建的 CSV 文件时
- deep-learning - 无法从“smart_open”导入名称“open”
- android - Android 工具提示显示在菜单项上
- python - 将 Pandas Series 转换为 Set 以逗号分隔值
- git - Git 保存分支之间的特定文件
- machine-learning - 为什么在 roc-auc 曲线中假阳性率和真阳性率加起来不等于 1?
- c++ - 在实例化之前推断函数模板的返回类型
- git - git pull whackiness,无法删除远程分支
- javascript - 为什么我的 equalSign 函数在运行时不起作用?