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

Flutter用StreamBuilder拉取API时报Future<dynamic>非Stream<List<dynamic>>子类型错误

错误原因

你给StreamBuilder的stream参数传入了Backend.getData(),但该方法是async修饰的异步方法,返回值类型为Future,不是Stream,类型不匹配所以抛出该错误。
同时你的代码逻辑存在冗余:你已经在initState中提前请求了接口数据存入_welcome变量,也做了加载状态判断,完全不需要额外嵌套StreamBuilder。


方案1:直接使用已请求的本地数据(改动最小)

直接删掉多余的StreamBuilder层,用已经拿到的_welcome渲染列表即可,修改Search_product.dart中waiting为false时的代码:

: Expanded(
    child: ListView.builder(
        padding: EdgeInsets.all(8),
        itemCount: _welcome.length,
        itemBuilder: (BuildContext context, int index) {
          Welcome item = _welcome[index];
          return Card(
            child: Column(
              children: <Widget>[
                ListTile(
                  leading: CircleAvatar(
                    radius: 30,
                    backgroundImage: NetworkImage(item.image),
                  ),
                  title: Text(item.title),
                  subtitle: Text(item.description),
                  trailing: Text(item.price.toString()),
                )
              ],
            ),
          );
        }),
  )

方案2:若确实需要使用StreamBuilder

首先需要把Future类型的返回值转成Stream,你可以直接调用Future的asStream()方法,同时调整逻辑删掉initState里的冗余请求:

  1. 先修改Backend.dart中getData的返回值类型声明,避免隐式dynamic问题:
static Future<List<Welcome>> getData() async {
  try {
    var url = Uri.parse('https://fakestoreapi.com/products');
    var response = await http.get(url);
    if (response.statusCode == 200) {
      return welcomeFromJson(response.body);
    } else {
      throw Exception('接口请求失败');
    }
  } catch (e) {
    rethrow;
  }
}
  1. 修改Search_product.dart的代码,去掉initState里的请求,直接用StreamBuilder处理加载、错误、渲染逻辑:
// 删掉原来的_welcome、waiting变量,修改build里的容器部分
Container(
  child: Expanded(
    child: StreamBuilder<List<Welcome>>(
        stream: Backend.getData().asStream(),
        builder: (BuildContext context, AsyncSnapshot<List<Welcome>> snapshot) {
          // 加载状态
          if (snapshot.connectionState == ConnectionState.waiting) {
            return Center(
              child: SizedBox(
                width: 50,
                height: 50,
                child: CircularProgressIndicator(),
              ),
            );
          }
          // 错误状态
          if (snapshot.hasError) {
            return Center(child: Text('加载失败:${snapshot.error}'));
          }
          // 渲染数据
          List<Welcome> list = snapshot.data!;
          return ListView.builder(
              padding: EdgeInsets.all(8),
              itemCount: list.length,
              itemBuilder: (BuildContext context, int index) {
                Welcome item = list[index];
                return Card(
                  child: Column(
                    children: <Widget>[
                      ListTile(
                        leading: CircleAvatar(
                          radius: 30,
                          backgroundImage: NetworkImage(item.image),
                        ),
                        title: Text(item.title),
                        subtitle: Text(item.description),
                        trailing: Text(item.price.toString()),
                      )
                    ],
                  ),
                );
              });
        }),
  ),
)

额外注意

你原来的代码里写了snapshot.data[index].welcome.image是错误写法,接口返回的列表元素本身就是Welcome类型对象,不需要额外加.welcome调用属性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 06:54:00