简体   繁体   English

Flutter:需要加载值,然后对 Futurebuilder 进行 firebase 查询导致 RangeError(索引)

[英]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 ?我也对这种格式感到困惑……为什么要使用FutureFutureBuilder 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM