首页 > 解决方案 > 队列在飞镖/颤振中

问题描述

我有一个来自 firestore 的 Document 快照,它以双精度形式返回多个值,因此我创建了一个队列变量以将其添加到我的构建方法中。它打印出结果,但是当我点击其他页面时它有一个错误。如下我的代码页所述,该错误已打印在控制台中。当我第一次运行我的应用程序时,该错误不会出现,但仅在我单击页面时才会出现。

我还注释掉了 sortDistance() 函数中的 sort 方法,但是当它被排序时,文档快照值不再像卡片那样以排序顺序打印。

任何帮助将不胜感激。

这是我的代码:

import 'dart:async';
import 'dart:math';
import 'dart:collection';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';

import 'package:geolocator/geolocator.dart';
import 'package:cloud_firestore/cloud_firestore.dart';

import 'package:myapp/Cards/Store Card.dart';
import 'package:myapp/MainMenuPages/First%20Menu.dart';
import 'package:myapp/MainMenuPages/Second%20Menu.dart';
import 'package:myapp/MainMenuPages/Third%20Menu.dart';
import 'package:myapp/MainMenuPages/Fourth%20Perkins%20Menu.dart';
import 'package:myapp/MainMenuPages/Fifth%20Menu.dart';


class StoreList extends StatefulWidget {

  @override
  _StoreListState createState() => _StoreListState();
}


class _StoreListState extends State<StoreList> {

  StreamSubscription<QuerySnapshot> subscription;
  List storeList;

  final CollectionReference collectionReference = Firestore.instance.collection('stores');

  Geolocator geolocator = Geolocator();

  bool sort = true;

   Queue timeQueue = Queue();
   Queue endTimeQueue = Queue();

  Future getLocation() async {
    var currentLocation;
    try {
      currentLocation = await geolocator.getCurrentPosition(
          desiredAccuracy: LocationAccuracy.high);
    } catch (e) {
      currentLocation = null;
    }
    return currentLocation;
  }

   double calculateDistance(lat1, lon1, lat2, lon2){
    var p = 0.017453292519943295;
    var c = cos;
    var a = 0.5 - c((lat2 - lat1) * p)/2 +
        c(lat1 * p) * c(lat2 * p) *
            (1 - c((lon2 - lon1) * p))/2;
    return 12742 * asin(sqrt(a));
  }

   double distance(Position position, DocumentSnapshot snapshot) {
    final double myPositionLat = position.latitude;
    final double myPositionLong = position.longitude;
    final double lat = snapshot.data['latitude'];
    final double long = snapshot.data['longitude'];

    double totalTime = calculateDistance(myPositionLat, myPositionLong, lat, long) * 60 / 28;
    double totalFinalTime = calculateDistance(myPositionLat, myPositionLong, lat, long) * 60 / 16;

    timeQueue.add(totalTime);
    endTimeQueue.add(totalFinalTime);

     print(totalTime);
     print(totalFinalTime);
     return totalTime;
  }

  void sortDistance(){
    subscription = collectionReference.snapshots().listen((data) async {

      final location = await getLocation();
      final documents = data.documents.where((snapshot) => distance(location, snapshot) <= 40).toList();

//      documents.sort((a, b) {
//        final distanceA = distance(location, a);
//        final distanceB = distance(location, b);
//        return distanceA.compareTo(distanceB);
//      });

      setState(()  {
        storeList = documents;
      });
    });
  }



  @override
  void initState() {
    super.initState();
    sortDistance();
  }



  @override
  void dispose() {
    subscription?.cancel();
    super.dispose();
  }



  @override
  Widget build(BuildContext context) {

    return storeList != null ?

      ListView.builder(
          itemCount: storeList.length,
          itemBuilder: (context, index) {


            double timeDisplay = timeQueue.removeFirst();
            double endTimeDisplay = endTimeQueue.removeFirst();


            String imgPath = storeList[index].data['image'];
            String storeTextPath = storeList[index].data['name'];
            String locationNamePath = storeList[index].data['location'];

            return StoreCard(
              etaText: timeDisplay.toInt(),
              etaText2: endTimeDisplay.toInt(),
              locationText: locationNamePath,
              storeText: storeTextPath,
              assetImage: Image.network(imgPath),

              function: (){ if (merchantTextPath == 'First') {
                  Navigator.pushNamed(context, FirstMenu.id);
                } else if (merchantTextPath == 'Second'){
                  Navigator.pushNamed(context, SecondMenu.id);
                } else if (merchantTextPath == 'Third'){
                  Navigator.pushNamed(context, ThirdMenu.id);
                } else if (merchantTextPath == 'Fourth'){
                  Navigator.pushNamed(context, FourthMenu.id);
                } else if (merchantTextPath == 'Fifth'){
                  Navigator.pushNamed(context, FifthMenu.id);
                }
              },
            );
          })

        : Center(child: CircularProgressIndicator());
  }
}

控制台产生这个:

════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following StateError was thrown building:
Bad state: No element

When the exception was thrown, this was the stack: 
#0      ListQueue.removeFirst (dart:collection/queue.dart:731:25)
#1      _StoreState.build.<anonymous closure> (package:swiftbee/StoreCategories/Store%20List.dart:145:44)
#2      SliverChildBuilderDelegate.build (package:flutter/src/widgets/sliver.dart:446:15)
#3      SliverMultiBoxAdaptorElement._build.<anonymous closure> (package:flutter/src/widgets/sliver.dart:1260:67)
#4      _HashMap.putIfAbsent (dart:collection-patch/collection_patch.dart:139:29)
...
════════════════════════════════════════════════════════════════════════════════════════════════════

标签: firebaseflutterdartgoogle-cloud-firestore

解决方案


似乎timeQueue没有任何元素。因此,请执行以下操作:

if(timeQueue.isNotEmpty){
  double timeDisplay = timeQueue.removeFirst();
}

推荐阅读