我有一个清单是从有状态窗口小部件的异步调用中填充的。它获取列表的第一项(实际上应该只是一项),并将其内容显示在卡中。
当我导航到屏幕时,它说没有元素与[0]的红色大屏幕相遇,但是屏幕几乎立即消失了(约0.5秒)。我假设这意味着呼叫正在完成,错误消失了。但是,这会在用户随机看到错误时带来非常差的用户体验。
我尝试在构建之前将异步调用放入init方法中-但是,错误仍在发生。
响应页面:
import 'dart:convert';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'package:location/location.dart';
import 'package:marketapp/Areas/Meet/MeetDetailsPage.dart';
class ResponsePage extends StatefulWidget {
static const int = 5;
static const routeName = '/responsepage';
final ResponsePageArguments rpa;
ResponsePage({Key key, @required this.rpa}) : super(key: key);
// Create initial state of the Meet Page
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return ResponsePageState();
}
}
class ResponsePageState extends State<ResponsePage> {
Location location = Location();
LocationData currentLocation;
var isLoading = false;
var id;
var meets = new List<MeetModel>();
@override
Widget build(BuildContext context) {
// TODO: implement build
final _formKey = GlobalKey<FormState>();
return Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Card(
child: ListTile(
title: Text(meets[0].host + " wants to meet you!"),
subtitle: Text("Requested at " + meets[0].requestTime),
)),
Padding(
padding: const EdgeInsets.symmetric(
vertical: 10.0, horizontal: 5.0),
child: Row(children: <Widget>[
RaisedButton(
onPressed: () {
declineRequest(id);
},
child: Text('Decline')),
RaisedButton(
onPressed: () {
// Validate returns true if the form is valid, false otherwise
acceptRequest(id);
},
child: Text('Accept'),
),
]))
]));
}
@override
initState() {
getMeet(widget.rpa.id);
id = widget.rpa.id;
super.initState();
location.onLocationChanged().listen((value) {
if (this.mounted) {
setState(() {
currentLocation = value;
});
}
});
}
acceptRequest(id) async {
setState(() {
isLoading = true;
});
final url = 'https://.azurewebsites.net/Meets/MeetResponse/$id';
var userToken = await getToken();
print("Token printed " + userToken.toString());
var body = jsonEncode({'latitude': currentLocation.latitude.toString(),
'longitude' : currentLocation.longitude.toString()});
print("Current Latitude: " + currentLocation.latitude.toString());
print("Current Longitude: " + currentLocation.longitude.toString());
/*final responseBody = (await http.get(
'https://.azurewebsites.net/Auths/RegisterDevice?deviceToken=$deviceToken&userToken=$userToken'))
.body;*/
/*return */
http.post(
url,
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer $userToken"
},
body: body
).then((http.Response response) {
print("Accept Response Status: ${response.statusCode}");
print("Accept Response Body: ${response.body}");
setState(() {
isLoading = false;
});
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) =>
MeetDetailsPage(mdpa: MeetDetailsPageArguments(id))));
});
}
declineRequest(id) async {
setState(() {
isLoading = true;
});
final url = 'https://.net/Meets/MeetResponse/$id';
var userToken = await getToken();
print("Token printed " + userToken.toString());
var body = jsonEncode({'userToken': '$userToken'});
/*final responseBody = (await http.get(
'https://.net/Auths/RegisterDevice?deviceToken=$deviceToken&userToken=$userToken'))
.body;*/
/*return */
http.post(
url,
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer $userToken"
},
/*body: body*/
).then((http.Response response) {
print("Decline Response Status: ${response.statusCode}");
print("Decline Response Body: ${response.body}");
setState(() {
isLoading = false;
});
var responseBody = response.body;
});
}
getMeet(id) async {
setState(() {
isLoading = true;
});
final url = 'https://``````````````.net/Meets/Get/$id';
var userToken = await getToken();
print("Token printed " + userToken.toString());
var body = jsonEncode({'userToken': '$userToken'});
/*final responseBody = (await http.get(
'https://``````````.net/Auths/RegisterDevice?deviceToken=$deviceToken&userToken=$userToken'))
.body;*/
/*return */
http.get(
url,
headers: {"Authorization": "Bearer $userToken"},
/*body: body*/
).then((http.Response response) async {
print("Get Response Status: ${response.statusCode}");
print("Get Response Body: ${response.body}");
setState(() {
isLoading = false;
});
var responseBody = response.body;
meets = MeetModel.fromJsonList(json.decode(responseBody));
});
}
}
Future<String> getToken() async {
final storage = new FlutterSecureStorage();
return await storage.read(key: 'token');
}
class ResponsePageArguments {
String id;
ResponsePageArguments(this.id);
}
// Code below is useless
class MeetModel {
String meetId;
String host;
String hostId;
String address;
String city;
String zip;
String category;
String latitude;
String longitude;
String product;
String productId;
String reference;
String hostPlaceId;
String venueAddress;
String venuePlaceId;
String venueLatitude;
String venueLongitude;
String recipient;
String recipientAddress;
String recipientZip;
String recipientCity;
String recipientPlaceID;
String recipientLatitude;
String recipientLongitude;
String requestTime;
String responseTime;
String recipientId;
String isArchived;
String meetType;
MeetModel.fromJson(obj) {
this.meetId = obj['MeetId'].toString();
this.host = obj['Host'].toString();
this.address = obj['Address'].toString();
this.city = obj['City'].toString();
this.zip = obj['Zip'].toString();
this.category = obj['Category'].toString();
this.latitude = obj['Latitude'].toString();
this.longitude = obj['Longitude'].toString();
this.product = obj['Product'].toString();
this.productId = obj['ProductId'].toString();
this.reference = obj['Reference'].toString();
this.hostPlaceId = obj['HostPlaceId'].toString();
this.venueAddress = obj['VenueAddress'].toString();
this.venuePlaceId = obj['VenuePlaceId'].toString();
this.venueLatitude = obj['VenueLatitude'].toString();
this.venueLongitude = obj['VengueLongitude'].toString();
this.recipient = obj['Recipient'].toString();
this.recipientAddress = obj['RecipientAddress'].toString();
this.recipientZip = obj['RecipientZip'].toString();
this.recipientPlaceID = obj['RecipientPlaceID'].toString();
this.recipientLatitude = obj['RecipientLatitude'].toString();
this.recipientLongitude = obj['RecipientLongitude'].toString();
this.requestTime = obj['RequestTime'].toString();
this.responseTime = obj['ResponseTime'].toString();
this.hostId = obj['HostId'].toString();
this.recipientId = obj['RecipientId'].toString();
this.isArchived = obj['IsArchived'].toString();
this.meetType = obj['MeetType'].toString();
}
static List<MeetModel> fromJsonList(jsonList) {
return jsonList.map<MeetModel>((obj) => MeetModel.fromJson(obj)).toList();
}
}
会议页面:
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:marketapp/Areas/Meet/ResponsePage.dart';
import 'MeetDetailsPage.dart';
class MeetsPage extends StatefulWidget {
@override
State createState() => new MeetsPageState();
}
class MeetsPageState extends State<MeetsPage> {
var meets = new List<MeetModel>();
var isLoading = false;
_fetchData() async {
setState(() {
isLoading = true;
});
final url = 'https://.azurewebsites.net/Meets/GetAll';
var userToken = await getToken();
print("Token printed " + userToken.toString());
var body = jsonEncode({'userToken': '$userToken'});
/*final responseBody = (await http.get(
'https://.azurewebsites.net/Auths/RegisterDevice?deviceToken=$deviceToken&userToken=$userToken'))
.body;*/
/*return */
http.post(
url,
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer $userToken"
},
/*body: body*/
).then((http.Response response) {
print("GetAll Response Status: ${response.statusCode}");
print("GetAll Response Body: ${response.body}");
setState(() {
isLoading = false;
});
var responseBody = response.body;
meets = MeetModel.fromJsonList(json.decode(responseBody));
});
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
/*appBar: AppBar(
title: Text("Meet List"),
backgroundColor: Colors.indigo,
),*/
body: isLoading
? Center(
child: CircularProgressIndicator(),
)
: ListView.builder(
itemCount: meets.length,
itemBuilder: (context, index) {
if (meets[index].host == "xxxxxx@gmail.com") { // Do not hard code email.
return ListTile(
onTap: () {
if (meets[index].venueAddress != "null") {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MeetDetailsPage(
mdpa: MeetDetailsPageArguments(
meets[index].meetId))));
} else if (meets[index].venueAddress == "null") {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ResponsePage(
rpa: ResponsePageArguments(
meets[index].meetId))));
}
},
title: Text(
meets[index].recipient,
style: TextStyle(fontWeight: FontWeight.w500)),
trailing: Icon(
Icons.map,
color: Colors.blue[500],
),
subtitle: Text(meets[index].requestTime),
);
} else {
return ListTile(
onTap: () {
if (meets[index].venueAddress != "null") {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MeetDetailsPage(
mdpa: MeetDetailsPageArguments(
meets[index].meetId))));
} else if (meets[index].venueAddress == "null") {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ResponsePage(
rpa: ResponsePageArguments(
meets[index].meetId))));
}
},
title: Text(
meets[index].host,
style: TextStyle(fontWeight: FontWeight.w500)),
trailing: Icon(
Icons.map,
color: Colors.blue[500],
),
subtitle: Text(meets[index].requestTime),
);
}
},
));
}
@override
void initState() {
_fetchData();
super.initState();
}
}
class MeetModel {
String meetId;
String host;
String hostId;
String address;
String city;
String zip;
String category;
String latitude;
String longitude;
String product;
String productId;
String reference;
String hostPlaceId;
String venueAddress;
String venuePlaceId;
String venueLatitude;
String venueLongitude;
String recipient;
String recipientAddress;
String recipientZip;
String recipientCity;
String recipientPlaceID;
String recipientLatitude;
String recipientLongitude;
String requestTime;
String responseTime;
String recipientId;
String isArchived;
String meetType;
MeetModel.fromJson(obj) {
this.meetId = obj['MeetId'].toString();
this.host = obj['Host'].toString();
this.address = obj['Address'].toString();
this.city = obj['City'].toString();
this.zip = obj['Zip'].toString();
this.category = obj['Category'].toString();
this.latitude = obj['Latitude'].toString();
this.longitude = obj['Longitude'].toString();
this.product = obj['Product'].toString();
this.productId = obj['ProductId'].toString();
this.reference = obj['Reference'].toString();
this.hostPlaceId = obj['HostPlaceId'].toString();
this.venueAddress = obj['VenueAddress'].toString();
this.venuePlaceId = obj['VenuePlaceId'].toString();
this.venueLatitude = obj['VenueLatitude'].toString();
this.venueLongitude = obj['VengueLongitude'].toString();
this.recipient = obj['Recipient'].toString();
this.recipientAddress = obj['RecipientAddress'].toString();
this.recipientZip = obj['RecipientZip'].toString();
this.recipientPlaceID = obj['RecipientPlaceID'].toString();
this.recipientLatitude = obj['RecipientLatitude'].toString();
this.recipientLongitude = obj['RecipientLongitude'].toString();
this.requestTime = obj['RequestTime'].toString();
this.responseTime = obj['ResponseTime'].toString();
this.hostId = obj['HostId'].toString();
this.recipientId = obj['RecipientId'].toString();
this.isArchived = obj['IsArchived'].toString();
this.meetType = obj['MeetType'].toString();
}
static List<MeetModel> fromJsonList(jsonList) {
return jsonList.map<MeetModel>((obj) => MeetModel.fromJson(obj)).toList();
}
}
Future<String> getToken() async {
final storage = new FlutterSecureStorage();
return await storage.read(key: 'token');
}
class Backend {
static Future<List<MeetModel>> GetAll(userToken) async {
final url = 'https://.net/Auths/RegisterDevice';
var body = jsonEncode({'userToken': '$userToken'});
/*final responseBody = (await http.get(
'https://.azurewebsites.net/Auths/RegisterDevice?deviceToken=$deviceToken&userToken=$userToken'))
.body;*/
return http
.post(url,
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer $userToken"
},
body: body)
.then((http.Response response) {
print("GetAll Response Status: ${response.statusCode}");
print("GetAll Response Body: ${response.body}");
var responseBody = response.body;
return MeetModel.fromJsonList(json.decode(responseBody));
});
}
}
该错误仍然会出现,但是在异步调用结束时消失了。注意-当您从Meets列表中选择一个项目时,会发生此错误-它会导航到ResponsePage,并且在短暂的一秒钟内,会出现红色闪烁,表明列表中没有足够的项目。当呼叫以正确的形式结束时,此错误消失。
在满足列表中的数据完成填充之前,是否有办法停止构建卡?