firebase - 队列在飞镖/颤振中
问题描述
我有一个来自 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)
...
════════════════════════════════════════════════════════════════════════════════════════════════════
解决方案
似乎timeQueue
没有任何元素。因此,请执行以下操作:
if(timeQueue.isNotEmpty){
double timeDisplay = timeQueue.removeFirst();
}
推荐阅读
- android - Android / 任务 checkDebugAarMetadata 执行失败 / 执行 CheckAarMetadataWorkAction 时发生故障
- java - 如何使用嵌套循环打印数组的元素,这些元素加在一起形成同一个数组的总和?
- python - Flask WTForms,如何为 SelectField 的选项添加附加属性?
- java - 在我的代码中,getArgument 每次都返回 null
- python - 提高 CNN 模型的准确性(陷入非常低的准确性)
- android - 从 AOSP 源代码树构建 Android 系统应用
- java - 来自 ZipInputStream 的 XMLEventReader 关闭流
- reactjs - 带有有效负载 {"name":"Home","params":{} 的操作 'NAVIGATE' 未被任何导航器处理
- reactjs - 使用 useState 在另一个对象中填充一个对象
- java - 由于 JRE 版本,Java 程序无法运行