Home > Software engineering >  Flutter: Need to load values and then make a firebase query for Futurebuilder caused RangeError (ind
Flutter: Need to load values and then make a firebase query for Futurebuilder caused RangeError (ind

Time:09-08

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.

My problem: I have to initialize Future<List> futureEvents in the onInit state, otherwise Flutter complains. At the time he didn't have the location yet.

So I call the function again at the end.

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.

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();
                    }
                  },
                ),

CodePudding user response:

Have you tried to just put the _getEvents() Future inside the FutureBuilder directly instead of using it as a late variable? I’m also confused by this format… why use a Future and a 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. Then take away the FutureBuilder and just use a ListView.builder. Just search how to create a ListView from a list, it’s very simple.

  • Related