You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何对StreamBuilder接收的Firestore筛选后数据按距离排序并获取生成的列表?

Hey there! Let's tackle your two requirements one by one—sorting the displayed trips by calculated distance, and accessing the list generated by .toList(). Here's how you can adjust your code to make this work smoothly:


1. Sorting Trips by Calculated Distance

The issue with your current code is that you're generating UI widgets directly while filtering, which leaves no way to collect and sort by the distance value. Instead, we'll first filter and collect valid trips along with their calculated distances, sort that list, then build the UI from the sorted data.

Here's the revised code:

Flexible(
  child: StreamBuilder<QuerySnapshot>(
    stream: _usersStream,
    builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
      if (snapshot.hasError) {
        return const Text('Error');
      }
      if (snapshot.connectionState == ConnectionState.waiting) {
        return const Text("Loading");
      }

      // Step 1: Filter valid trips and store them with their calculated distance
      final validTrips = <Map<String, dynamic>>[];
      for (final document in snapshot.data!.docs) {
        final data = document.data()! as Map<String, dynamic>;
        final startLocation = data['start_location'] as String;
        
        // Skip trips where start location matches the specified place
        if (startLocation == widget.placename) continue;

        final coord = data['coord'] as String;
        final splitted = coord.split('/');
        
        for (int i = 0; i < splitted.length - 1; i++) {
          final coordPair = splitted[i];
          final latLng = coordPair.split('-');
          final distance = calculateDistance(
            widget.place_latlng.latitude,
            widget.place_latlng.longitude,
            double.parse(latLng[0]),
            double.parse(latLng[1]),
          );

          // Add to valid list if distance is under 1 unit (adjust unit if needed)
          if (distance < 1) {
            validTrips.add({
              ...data,
              'distance': distance, // Attach the calculated distance for sorting
            });
            break; // Match your original logic: take first valid coord per document
          }
        }
      }

      // Step 2: Sort the valid trips by distance (ascending = closest first)
      validTrips.sort((a, b) => (a['distance'] as double).compareTo(b['distance'] as double));

      // Step 3: Build the ListView from the sorted list
      return ListView(
        children: validTrips.map((trip) {
          return GestureDetector(
            onTap: () {
              // Your onTap logic here
            },
            child: buildTripCard(
              context,
              start_location: trip['start_location'] as String,
              end_location: trip['end_location'] as String,
              date: trip['date'] as String,
              time: trip['time'] as String,
              price: trip['price'] as String,
              name_surname: trip['name_surname'] as String,
              userId: trip['user_id'] as String,
            ),
          );
        }).toList(),
      );
    },
  ),
)

Key Notes:

  • We first iterate through all Firestore documents, filter out invalid trips, and store valid ones with their calculated distance in the validTrips list.
  • The sort method orders trips by distance (closest first). Reverse the comparison (b['distance'].compareTo(a['distance'])) if you want farthest trips first.
  • The break after adding a valid trip matches your original logic (each document only contributes one trip if any coord meets the distance requirement). Remove it if you need to include multiple entries per document.

2. Accessing the List Generated by .toList()

In the revised code, the validTrips variable is exactly the list you're looking for—it's the filtered, sorted collection of trip data before converting to UI widgets. You can access it directly in the builder function for any additional logic:

// Example: Print the number of valid trips
print('Found ${validTrips.length} matching trips');

// Example: Access the first trip's data
if (validTrips.isNotEmpty) {
  print('Closest trip start: ${validTrips.first['start_location']}');
}

If you need to use this list outside the StreamBuilder (e.g., in another method of your widget), store it in a state variable:

  1. In your State class, add:
    List<Map<String, dynamic>>? _sortedTrips;
    
  2. In the builder function, after sorting:
    setState(() {
      _sortedTrips = validTrips;
    });
    
  3. Now you can access _sortedTrips anywhere in your state class.

内容的提问来源于stack exchange,提问作者Hakan Or

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 21:02:35