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

Flutter Rest Api开发报错:空检查运算符用于空值

问题解决:Null check operator used on a null value

错误根源分析

  • 强制解包空值:代码中snapshots.data!使用!强制解包,但当API请求失败(网络异常、接口返回错误、数据解析失败)时,snapshots.data会为null,直接解包触发该错误。同时你未处理请求失败的情况,仅判断了连接完成状态,忽略了错误分支。
  • Future重复创建:_body()方法每次调用都会新建ApiService并发起请求,组件重建时会重复触发请求,可能引发异常。
  • 子组件无法接收数据:_hotels方法里的HotelScreen、HotelDescription用const修饰,无法传递当前索引的酒店数据,后续必然出现数据无法展示的问题。

修复步骤

1. 处理请求错误与空值

修改FutureBuilder逻辑,先判断错误状态,再安全处理数据:

FutureBuilder _body() {
  final apiService = ApiService(Dio(BaseOptions(contentType: "application/json")));
  return FutureBuilder<List<HotelModel>>(
    future: apiService.getHotels(),
    builder: (context, snapshots) {
      if (snapshots.hasError) {
        return Center(child: Text('请求失败: ${snapshots.error}'));
      }
      
      if (snapshots.connectionState == ConnectionState.done) {
        final List<HotelModel> hotels = snapshots.data ?? [];
        return _hotels(hotels);
      } else {
        return const Center(child: CircularProgressIndicator());
      }
    },
  );
}

2. 避免Future重复执行

将StatelessWidget改为StatefulWidget,在initState中仅发起一次请求:

class HotelPage extends StatefulWidget {
  const HotelPage({Key? key}) : super(key: key);

  @override
  State<HotelPage> createState() => _HotelPageState();
}

class _HotelPageState extends State<HotelPage> {
  late Future<List<HotelModel>> _hotelsFuture;

  @override
  void initState() {
    super.initState();
    final apiService = ApiService(Dio(BaseOptions(contentType: "application/json")));
    _hotelsFuture = apiService.getHotels();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.grey[200],
      appBar: AppBar(
        centerTitle: true,
        title: const Text(
          'Отель',
          style: TextStyle(color: Colors.black),
        ),
        toolbarHeight: 50,
        backgroundColor: backgroundtheme,
        elevation: 0,
      ),
      body: FutureBuilder<List<HotelModel>>(
        future: _hotelsFuture,
        builder: (context, snapshots) {
          if (snapshots.hasError) {
            return Center(child: Text('请求失败: ${snapshots.error}'));
          }
          
          if (snapshots.connectionState == ConnectionState.done) {
            final List<HotelModel> hotels = snapshots.data ?? [];
            return _hotels(hotels);
          } else {
            return const Center(child: CircularProgressIndicator());
          }
        },
      ),
    );
  }
}

3. 传递数据给子组件

去掉子组件的const修饰,将当前酒店数据传入:

Widget _hotels(List<HotelModel> hotels) {
  return ListView.builder(
    itemCount: hotels.length,
    itemBuilder: (context, index) {
      final hotel = hotels[index];
      return Stack(
        children: [
          Column(
            children: [
              HotelScreen(hotel: hotel), // 需确保HotelScreen支持接收hotel参数
              HotelDescription(hotel: hotel), // 同理传递数据
            ],
          ),
          const BottomButtonWidget()
        ],
      );
    },
  );
}

4. 检查数据模型解析

若请求成功但数据仍为null,需排查:

  • 接口返回的JSON结构与HotelModel字段是否完全匹配(字段名、数据类型)
  • HotelModel是否添加了正确的序列化注解(如@JsonSerializable()),且已运行build_runner生成序列化代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 16:03:15