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

Flutter中如何从Supabase获取指定post_id的数据?

解决方案与思路

方案1:实时监听(Stream)

你的现有Stream代码已经具备列表展示能力,只需添加post_id=1的过滤条件即可。Supabase的Stream支持链式调用过滤方法,修改后代码如下:

fetchData() {
  final stream = Supabase.instance.client
      .from('post_ingredient')
      .stream(primaryKey: ['ingredient_id'])
      .eq('post_id', 1) // 过滤post_id为1的行
      .order('order', ascending: true);

  return StreamBuilder<List<Map<String, dynamic>>>(
    stream: stream,
    builder: (context, snapshot) {
      if (snapshot.connectionState == ConnectionState.waiting) {
        return const Center(child: CircularProgressIndicator());
      }
      if (snapshot.hasError) {
        return Center(child: Text('加载出错: ${snapshot.error}'));
      }
      final ingredients = snapshot.data ?? [];

      return ListView.builder(
        itemCount: ingredients.length,
        itemBuilder: (context, index) {
          return Text(ingredients[index]['ingredient'].toString());
        },
      );
    }
  );
}

这个方案适合需要实时同步数据的场景,当post_id=1的食材数据发生变化时,UI会自动刷新。

方案2:单次查询(Select)

如果不需要实时监听数据变化,用select()做单次查询更高效。你之前的.select('ingredient').eq('post_id', 1)是正确的,不需要用single()(single()仅适用于返回单行数据的场景),直接用get()获取列表,配合FutureBuilder处理异步结果:

Future<List<String>> fetchIngredients() async {
  final response = await Supabase.instance.client
      .from('post_ingredient')
      .select('ingredient')
      .eq('post_id', 1)
      .order('order', ascending: true);
  
  return response.map((item) => item['ingredient'].toString()).toList();
}

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: _appBar(),
    body: FutureBuilder<List<String>>(
      future: fetchIngredients(),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return const Center(child: CircularProgressIndicator());
        }
        if (snapshot.hasError) {
          return Center(child: Text('加载出错: ${snapshot.error}'));
        }
        final ingredients = snapshot.data ?? [];

        return ListView.builder(
          itemCount: ingredients.length,
          itemBuilder: (context, index) {
            return Text(ingredients[index]);
          },
        );
      },
    ),
  );
}

实用技巧与选择思路

  • Stream vs Select:
    • 需实时同步数据(如食材可能被修改)→ 选Stream;
    • 数据静态或仅需加载一次→ 选Select+FutureBuilder(性能更优)。
  • 字段名匹配:注意你之前写的.eq('post', 1)是错误的,数据库字段为post_id,必须严格对应。
  • 数据结构化:可将返回的Map转为自定义类(如Ingredient),提升代码可读性和维护性:
    class Ingredient {
      final int id;
      final String name;
      final int order;
    
      Ingredient({required this.id, required this.name, required this.order});
    
      factory Ingredient.fromMap(Map<String, dynamic> map) {
        return Ingredient(
          id: map['ingredient_id'],
          name: map['ingredient'],
          order: map['order'],
        );
      }
    }
    
    后续可将数据转为List<Ingredient>处理,逻辑更清晰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 07:16:11