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

Flutter结合Firestore实现动态路由:根据所选国家加载对应城市页面

Flutter 动态路由+Firestore 数据加载实现方案

1. 路由传参实现

在国家列表页面,给每个国家列表项绑定点击事件,通过RouteSettings传递国家的唯一标识(比如Firestore文档ID或国家名称):

GestureDetector(
  onTap: () {
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => const CityListPage(),
        // 传递国家标识,这里用Firestore文档ID示例
        settings: const RouteSettings(arguments: "china"),
      ),
    );
  },
  child: ListTile(title: const Text("中国")),
)

在城市列表页面,通过ModalRoute获取路由参数:

class CityListPage extends StatelessWidget {
  const CityListPage({super.key});

  @override
  Widget build(BuildContext context) {
    // 获取路由传递的国家标识
    final countryId = ModalRoute.of(context)!.settings.arguments as String;

    return Scaffold(
      appBar: AppBar(title: const Text("城市列表")),
      body: FutureBuilder<List<City>>(
        future: _loadCities(countryId),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const Center(child: CircularProgressIndicator());
          }
          if (snapshot.hasError) {
            return Center(child: Text("加载失败: ${snapshot.error}"));
          }
          final cities = snapshot.data ?? [];
          return ListView.builder(
            itemCount: cities.length,
            itemBuilder: (context, index) {
              final city = cities[index];
              return Card(
                child: Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Image.network(city.imageUrl, height: 150, width: double.infinity, fit: BoxFit.cover),
                      const SizedBox(height: 8),
                      Text(city.name, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
                      const SizedBox(height: 4),
                      Text(city.description),
                    ],
                  ),
                ),
              );
            },
          );
        },
      ),
    );
  }
}

2. Firestore数据查询与模型转换

先定义城市数据模型,方便从Firestore文档转换数据:

class City {
  final String name;
  final String imageUrl;
  final String description;

  City({required this.name, required this.imageUrl, required this.description});

  // 从Firestore文档映射为模型
  factory City.fromFirestore(DocumentSnapshot doc) {
    final data = doc.data() as Map<String, dynamic>;
    return City(
      name: data['name'] ?? '',
      imageUrl: data['imageUrl'] ?? '',
      description: data['description'] ?? '',
    );
  }
}

然后实现Firestore查询方法,根据国家标识获取对应城市:

Future<List<City>> _loadCities(String countryId) async {
  final citiesSnapshot = await FirebaseFirestore.instance
      .collection('countries')
      .doc(countryId)
      .collection('cities')
      .get();
  
  return citiesSnapshot.docs.map((doc) => City.fromFirestore(doc)).toList();
}

3. Firestore数据结构建议

推荐的数据库层级结构:

countries (集合)
  ├─ china (文档ID: china)
  │  └─ cities (子集合)
  │     ├─ beijing (文档)
  │     │  ├─ name: "北京"
  │     │  ├─ imageUrl: "https://example.com/beijing.jpg"
  │     │  └─ description: "中国首都..."
  │     ├─ shanghai (文档)
  │     └─ guangzhou (文档)
  ├─ usa (文档ID: usa)
  │  └─ cities (子集合)
  └─ japan (文档ID: japan)
     └─ cities (子集合)

4. 数据流向示意图

数据流向:

  1. 用户点击国家列表页的某个国家 → 路由携带国家ID跳转到城市列表页
  2. 城市列表页接收国家ID → 向Firestore发起查询请求
  3. Firestore返回该国家下的所有城市数据 → 城市列表页渲染城市卡片(图片+描述)

内容的提问来源于stack exchange,提问作者Gytis Raudonius

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 22:15:16