Flutter中调用null对象的loadingStatus getter报错求助
解决Provider获取
loadingStatus时出现The getter 'loadingStatus' was called on null的问题 我来帮你分析这个问题的核心原因,以及给出具体的修复方案:
错误根源
你遇到的问题本质是组件首次执行build方法时,_generalService还未完成初始化:
- 在
initState里,你通过WidgetsBinding.instance.addPostFrameCallback来获取Provider实例,这个回调是在组件第一次build执行完毕后才会触发的。 - 首次
build时,_generalService还是初始的null状态,此时访问_generalService.loadingStatus自然会抛出空指针错误。 - 之所以应用还能正常运行,是因为回调触发后
_generalService被成功赋值,后续notifyListeners触发的UI重建就能正常访问这个属性了。
修复方案
方案1:在build中直接通过Provider.of获取实例(官方推荐)
这种方式能避免手动持有服务实例带来的生命周期冲突,是Provider的标准用法:
修改你的build方法,同时调整initState里的服务获取逻辑:
class _DoctorInfoPageState extends State<DoctorInfoPage> { @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((timeStamp) { // 添加listen: false,因为这里只需要获取实例,不需要监听变化 final generalService = Provider.of<GeneralService>(context, listen: false); final profileService = Provider.of<ProfileService>(context, listen: false); loadingReviews(generalService, profileService); }); } loadingReviews(GeneralService generalService, ProfileService profileService) async { generalService.setLoadingState(true); await profileService.getReviews(context); generalService.setLoadingState(false); } @override Widget build(BuildContext context) { // 每次build都获取最新的服务实例 final generalService = Provider.of<GeneralService>(context); return Scaffold( backgroundColor: Colors.white, appBar: AppBar( elevation: 0.0, centerTitle: true, backgroundColor: Colors.white, leading: IconButton( icon: Icon(Icons.chevron_left, size: 30, color: Const.appMainBlueColor), onPressed: () { print('test'); }, ), title: Text( "Doctor Info", style: TextStyle( color: Const.appMainBlueColor, fontWeight: FontWeight.w600, fontSize: 18), ), ), body: generalService.loadingStatus ? Center(child: PumpHeart(size: 35.0)) : SafeArea() ); } }
方案2:使用Consumer组件(更高效的响应式写法)
如果希望只有loadingStatus变化时才重建对应UI部分,用Consumer能提升性能:
@override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, appBar: AppBar( elevation: 0.0, centerTitle: true, backgroundColor: Colors.white, leading: IconButton( icon: Icon(Icons.chevron_left, size: 30, color: Const.appMainBlueColor), onPressed: () { print('test'); }, ), title: Text( "Doctor Info", style: TextStyle( color: Const.appMainBlueColor, fontWeight: FontWeight.w600, fontSize: 18), ), ), // 用Consumer包裹需要根据loadingStatus更新的UI body: Consumer<GeneralService>( builder: (context, generalService, child) { return generalService.loadingStatus ? Center(child: PumpHeart(size: 35.0)) : SafeArea(); }, ) ); }
注意initState里的服务获取同样需要加上listen: false参数。
方案3:临时初始化变量(不推荐,仅作应急)
如果想暂时保留当前的变量持有方式,可以在build中先判断变量是否为空:
class _DoctorInfoPageState extends State<DoctorInfoPage> { GeneralService _generalService; ProfileService _profileService; @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((timeStamp) { _generalService = Provider.of<GeneralService>(context); _profileService = Provider.of<ProfileService>(context); loadingReviews(); setState((){}); // 手动触发一次build,确保变量赋值后UI更新 }); } // ...其他代码 @override Widget build(BuildContext context) { // 先判断变量是否为空,避免首次build报错 if(_generalService == null) return const Center(child: SizedBox()); return Scaffold( // ...其他代码 body: _generalService.loadingStatus ? Center(child: PumpHeart(size: 35.0)) : SafeArea() ); } }
这种方式不够优雅,手动调用setState也不符合Provider的设计理念,因此更推荐前两种方案。
内容的提问来源于stack exchange,提问作者Khaled EL-Azab
相关产品推荐
相关产品推荐

