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
相关产品推荐
相关产品推荐

