[英]Flutter: Need to load values and then make a firebase query for Futurebuilder caused RangeError (index)
I'm trying to load the geo location first.我正在尝试首先加载地理位置。 Then I use this value to start a query which events are in a certain radius from this location.然后我使用这个值开始查询哪些事件在这个位置的某个半径内。
I want to display these events in a FutureBuilder.我想在 FutureBuilder 中显示这些事件。
My problem: I have to initialize Future<List> futureEvents in the onInit state, otherwise Flutter complains.我的问题:我必须在 onInit state 中初始化 Future<List> futureEvents,否则 Flutter 会抱怨。 At the time he didn't have the location yet.当时他还没有位置。
So I call the function again at the end.所以最后我再次调用 function。
So it happens that the error "RangeError (index): Invalid value: Valid value range is empty:1" is thrown until the method is called again after receiving the geo-location and I get the data.所以碰巧会抛出错误“RangeError(index):无效值:有效值范围为空:1” ,直到在接收到地理位置后再次调用该方法并获得数据。
Sorry for bad coding.抱歉编码不好。 One of my first Projects我的第一个项目之一
The InitState:初始化状态:
class _LocationPageState extends State<LocationPage> {
String? _currentAddress;
Position? _currentPosition;
late Future<List<Events>> futureEvents;
double locationRadius = 5;
@override
void initState() {
super.initState();
_getCurrentPosition();
futureEvents = _getEvents();
}
The called functions:调用函数:
Future<void> _getCurrentPosition() async {
final hasPermission = await _handleLocationPermission();
if (!hasPermission) return;
await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high)
.then((Position position) {
setState(() => _currentPosition = position);
_getAddressFromLatLng(_currentPosition!);
}).catchError((e) {
debugPrint(e);
});
}
Future<void> _getAddressFromLatLng(Position position) async {
await placemarkFromCoordinates(
_currentPosition!.latitude, _currentPosition!.longitude)
.then((List<Placemark> placemarks) {
Placemark place = placemarks[0];
setState(() {
_currentAddress = ' ${place.postalCode} ${place.locality} ';
});
currentPLZ = place.postalCode.toString();
futureEvents = _getEvents() as Future<List<Events>>;
}).catchError((e) {
debugPrint(e);
});
}
Future<List<Events>> _getEvents() async {
// get all PLZ in a radius
final response = await http.get(Uri.parse(
'https://www.suche-postleitzahl.org/geo-api.json?action=plz-umkreis&subaction=umkreis-osm&plz=' +
currentPLZ +
'&radius=' + locationRadius.toString()));
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
var jsondataPlz = jsonDecode(response.body);
List<PLZData> plzdataList = [];
for (var u in jsondataPlz) {
PLZData plzData = PLZData(u['postal_code'], u['name'], u['distance']);
plzdataList.add(plzData);
}
print(plzdataList.length);
print(plzdataList[1].name +
" Distanz:" +
plzdataList[1].distance +
" PLZ only" +
plzdataList[1].postal_code);
// get all events in the radius
List<Events> events = [];
if (plzdataList.isNotEmpty) {
for (var i = 0; plzdataList.length > i; i++) {
var singleEvent = await FirebaseFirestore.instance
.collection('Events')
.where('postCode', isEqualTo: plzdataList[i].postal_code)
.get();
if (singleEvent.docs.isNotEmpty) {
var singleEventList =singleEvent.docs.map((d) => Events.fromJson(d.data())).toList();
//add distance and regionname
for(var j = 0; singleEventList.length > j; j++){
singleEventList[j].distance = plzdataList[i].distance;
singleEventList[j].regionName = plzdataList[i].name;
}
events = events + singleEventList;
if (events[0].userID != null) {
print(events[0].userID);
print(events[i].distance);
}
}
}
}
//get userdata to the events
if (events.isEmpty) {
print("Es wurden keine Events gefunden");
} else {
for (var i = 0; events.length > i; i++) {
var userInformationSnap = await FirebaseFirestore.instance
.collection('users')
.where('__name__', isEqualTo: events[i].userID)
.get();
events[i].userInformation = userInformationSnap.docs
.map((d) => UsersForPosts.fromJson(d.data()))
.toList();
print(events[i].userInformation[0].username);
}
}
return events;
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load');
}
}
The FutureBuilder未来建造者
FutureBuilder<List<Events>>(
future: futureEvents,
builder: (context, snapshot) {
if (snapshot.hasData &&
snapshot.connectionState == ConnectionState.done) {
return ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(), //<--here
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
return Eventcard(
userPhoto: snapshot.data?[index].userInformation[0]
.userPhoto ?? "keine Info",
age: snapshot.data?[index].userInformation[0].age ??
"keine Info",
username: snapshot.data?[index].userInformation[0]
.username ?? "keine Info",
gender: snapshot.data?[index].userInformation[0]
.gender ?? "keine Info",
meetState: snapshot.data?[index].meetState ??
"keine Info",
postCode: snapshot.data?[index].postCode ??
"keine Info",
distance: snapshot.data?[index].distance ??
"keine Info",
regionName: snapshot.data?[index].regionName ??
"keine Info",
comment: snapshot.data?[index].comment ??
"keine Info",
headline: snapshot.data?[index].headline ??
"keine Info",
);
},
);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
} else {
// By default, show a loading spinner.
return const CircularProgressIndicator();
}
},
),
Have you tried to just put the _getEvents() Future
inside the FutureBuilder
directly instead of using it as a late variable?您是否尝试将_getEvents() Future
直接放在FutureBuilder
中,而不是将其用作后期变量? I'm also confused by this format… why use a Future
and a FutureBuilder
?我也对这种格式感到困惑……为什么要使用Future
和FutureBuilder
? It seems like you could just create an empty list events = []
then in the initState
call a new async function where you fetch the events from Firestore
and use that data to update the events
list through setState
.似乎您可以创建一个空列表events = []
然后在initState
中调用一个新的异步 function 从Firestore
获取事件并使用该数据通过setState
更新events
列表。 Then take away the FutureBuilder
and just use a ListView.builder
.然后拿走FutureBuilder
并使用ListView.builder
。 Just search how to create a ListView from a list, it's very simple.只需搜索如何从列表中创建 ListView,非常简单。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.