Flutter/Dart:带懒加载的列表如何按距离排序?
问题描述
我有一个包含纬度(lat)和经度(lng)的列表,希望按距离对其进行排序,但由于给列表添加了懒加载功能,实现起来十分困难,以下是我的完整代码:
class ListPage extends StatefulWidget { late final AppController appController; ListPage(appController){ this.appController = appController; } @override _ListPageState createState() => _ListPageState(); } class _ListPageState extends State<ListPage> { late double unitHeightValue; final myController = TextEditingController(); bool firstTime = false; String evseSearchField = ""; Evse evse = new Evse(evseID: 0, friendlyName: "", street: "", streetNumber: "", region: "", lat: 0.0, lng: 0.0, connectorList: [], cpSerial: "", img: ""); late List<EvsePanel> evsePanels = [new EvsePanel(evse, widget.appController, true)]; late TextField searchTextField = TextField( controller: myController, decoration: InputDecoration( border: InputBorder.none, hintText: 'Search', fillColor: Colors.white, ), ); final controller = ScrollController(); List<String> items = []; bool hasMore = true; int page = 1; bool isLoading = false; @override void initState(){ super.initState(); fetch(); controller.addListener(() { if (controller.position.maxScrollExtent == controller.offset) { fetch(); } }); } @override void dispose() { myController.dispose(); controller.dispose(); super.dispose(); } void refreshEvsePanels() async{ const refreshSeconds = const Duration(seconds: 5); Timer.periodic(refreshSeconds, (Timer t) { if(!mounted) { t.cancel(); return; } showEvsePanels(); }); } void showEvsePanels() async{ widget.appController.evseList.sort((a, b){ int nameComp = a.sort_availability.compareTo(b.sort_availability); if (nameComp == stationAvailability.available.index) { return a.distance.compareTo(b.distance); // '-' for descending } return nameComp; }); setState(() { if (evseSearchField.isEmpty){ int i = 0; if (tempEvses.length != 0){ evsePanels.clear(); while (i < tempEvses.length){ evsePanels.add(new EvsePanel(tempEvses[i], widget.appController, false)); i++; } } } else{ int i = 0; if (tempEvses.length != 0){ evsePanels.clear(); while (i < tempEvses.length){ if (containsIgnoreCase(tempEvses[i].friendlyName, evseSearchField)) evsePanels.add(new EvsePanel( tempEvses[i], widget.appController, false)); i++; } } } }); } List<Evse> tempEvses = []; Future fetch() async { if (isLoading) return; isLoading = true; const limit = 10; final url = Uri.parse('https://everywhere-dev.iccs.gr:18083/evse/getEvsesPaged?page=$page&pageLimit=$limit'); final response = await http.get(url); if (response.statusCode == 200) { final List newItems = json.decode(response.body)["results"]; setState(() { page++; isLoading = false; if (newItems.length <limit) { hasMore = false; } tempEvses.addAll(newItems.map<Evse>((items) { final evseID = items['evseID']; final friendlyName = items['friendlyName']; final street = items['street']; final streetNumber = items['streetNumber']; final region = items['region']; final lat = items['lat'] ?? 0.0; final lng = items['lng'] ?? 0.0; final connectorList = items['connectorList']; final cpSerial = items['cpSerial']; final img = items['img']; return new Evse(evseID: evseID, friendlyName: friendlyName, street: street, streetNumber: streetNumber, region: region, lat: lat, lng: lng, connectorList: [connectorList], cpSerial: cpSerial, img: img); }).toList()); for(int i=0 ; i<tempEvses.length; i++ ){ this.tempEvses[i].calculateDistance(widget.appController.currentLocation); // this.tempEvses[i].calculateAvailability(); this.tempEvses[i].isEvseFavorite(widget.appController.favoritesList); this.tempEvses[i].storePlugCounters(); } showEvsePanels(); }); } } Future refresh() async{ setState(() { isLoading = false; hasMore =true; page = 0; tempEvses.clear(); }); fetch(); } @override Widget build(BuildContext context) { if(!firstTime){ this.unitHeightValue = widget.appController.queryData.size.height * 0.001; showEvsePanels(); //refreshEvsePanels(); firstTime = true; } return SizedBox( height: widget.appController.queryData.size.height, width : widget.appController.queryData.size.width, child: Column( children: [ Container( height: widget.appController.queryData.size.height/12, width: widget.appController.queryData.size.width * (9/10), margin: EdgeInsets.all(5.0), decoration: BoxDecoration( color: widget.appController.themeController.appWhiteLightColor, boxShadow: [ BoxShadow( color: widget.appController.themeController.appGreyLightColor.withOpacity(0.6), spreadRadius: 1, blurRadius: 1, offset: Offset(0, 2), // changes position of shadow ), ], shape: BoxShape.rectangle, border: Border.all( color: Colors.transparent, ), borderRadius: BorderRadius.all(Radius.circular(10)) ), child:Row( mainAxisAlignment: MainAxisAlignment.center, children:[ Container( width: widget.appController.queryData.size.width * (7/10), child: searchTextField, ), Container( child: IconButton( color: widget.appController.themeController.appBlackDeepColor, tooltip: 'Search', icon: const Icon(Icons.search), iconSize: 32 * this.unitHeightValue, onPressed: () { this.evseSearchField = myController.text; showEvsePanels(); }, ), ), ] ), ), Expanded( child: RefreshIndicator( onRefresh: refresh, child: ListView.separated( separatorBuilder: (context, index) => Divider(), controller: controller, padding: const EdgeInsets.all(8), itemCount: evsePanels.length + 1, itemBuilder: (context, index) { if (index < evsePanels.length) { return evsePanels[index]; } else { return Padding( padding: const EdgeInsets.symmetric(vertical: 32), child: Center( child: hasMore ? const CircularProgressIndicator() : const Text('No more data to load'), ), ); } } ), ) ) ] ) ); } bool containsIgnoreCase(String str1, String str2) { return str1.toLowerCase().contains(str2.toLowerCase()); } }
内容的提问来源于stack exchange,提问作者Bill Tertis
相关产品推荐
相关产品推荐

