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

Flutter使用Image.network加载图片首次进入报Valid Value range is empty:0错误,重载后正常

问题根因
  • 你定义的galleryLoad是异步方法,Dart执行initState逻辑时不会等待异步方法执行完毕,会直接触发首次页面构建
  • 首次构建时网络请求尚未返回结果,images还是空数组,直接访问images[0]自然会抛出「有效取值范围为空,索引0不存在」的错误
  • 重载应用时此前的网络请求已经执行完成,images已经写入了返回的图片数据,所以不会触发报错
修复步骤

注意两个核心问题:

  1. 异步请求完成后需要调用setState通知Flutter重新渲染页面
  2. 页面构建时要先判断images数组是否有数据,再渲染对应组件

方案1:手动维护加载状态(改动最小)

首先在State类中初始化images为空数组:

List images = [];

修改galleryLoad方法,赋值后调用setState:

galleryLoad(String uid) async {
  EasyLoading.show(status: "Fetching Images");
  var url = '${serverPath}restaurantsGalleryImages';
  Map<String, String> requestHeaders = {
    'Content-type': 'application/json',
    'Accept': "application/json",
    'Authorization': "Bearer $uid",
  };
  var body = json.encoder.convert({});

  var response = await http
      .post(Uri.parse(url), headers: requestHeaders, body: body)
      .timeout(const Duration(seconds: 30));
  dprint('Response status: ${response.statusCode}');
  if (response.statusCode == 200) {
    EasyLoading.showSuccess("Images Fetched");
    var jsonResult = json.decode(response.body);
    // 赋值后调用setState触发页面重绘
    setState(() {
      images = jsonResult['images'];
    });
    print(images.length);
  } else {
    print("statusCode=${response.statusCode}");
  }
}

修改build方法,增加数据判断逻辑:

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text("Gallery",style: TextStyle(color: Colors.black),),
    ),
    body: images.isEmpty
        // 数据未加载完成时显示加载占位
        ? Center(child: CircularProgressIndicator())
        : Container(
            height: 400,
            width: 400,
            child: Image.network("https://nearxt.com/admin/public/${images[0]['image'].toString()}"),
          ),
  );
}

方案2:用FutureBuilder管理异步逻辑(更规范)

修改galleryLoad为带返回值的Future方法:

Future<List> galleryLoad(String uid) async {
  EasyLoading.show(status: "Fetching Images");
  var url = '${serverPath}restaurantsGalleryImages';
  Map<String, String> requestHeaders = {
    'Content-type': 'application/json',
    'Accept': "application/json",
    'Authorization': "Bearer $uid",
  };
  var body = json.encoder.convert({});
  var response = await http
      .post(Uri.parse(url), headers: requestHeaders, body: body)
      .timeout(const Duration(seconds: 30));
  dprint('Response status: ${response.statusCode}');
  if (response.statusCode == 200) {
    EasyLoading.showSuccess("Images Fetched");
    var jsonResult = json.decode(response.body);
    return jsonResult['images'];
  } else {
    print("statusCode=${response.statusCode}");
    return [];
  }
}

修改build方法,用FutureBuilder包裹渲染逻辑:

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text("Gallery",style: TextStyle(color: Colors.black),),
    ),
    body: FutureBuilder<List>(
      future: galleryLoad(account.token),
      builder: (context, snapshot) {
        // 加载中显示占位
        if (snapshot.connectionState == ConnectionState.waiting) {
          return Center(child: CircularProgressIndicator());
        }
        // 加载失败/无数据显示占位
        if (snapshot.hasError || !snapshot.hasData || snapshot.data!.isEmpty) {
          return Center(child: Text("暂无图片数据"));
        }
        final images = snapshot.data!;
        return Container(
          height: 400,
          width: 400,
          child: Image.network("https://nearxt.com/admin/public/${images[0]['image'].toString()}"),
        );
      },
    ),
  );
}

如果你要配合GridView.builder使用,直接把itemCount设置为images.length即可,也能避免索引越界问题。

内容的提问来源于stack exchange,提问作者ARPIT JAISWAL IET Student

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 13:06:04