Flutter跨类调用异步函数返回的List出现NoSuchMethodError如何解决
问题根因
- 你在
Item1组件中声明了接收_HomePageState类型的homepage参数,但创建Item1实例时没有传入当前HomePage的state实例,导致homepage为null,调用MissionData1时就抛出空指针异常 - 异步请求在
initState中触发,数据未加载完成时幻灯片就已经开始渲染,也会引发取值异常
修复方案
方案1(推荐,解耦父子组件):修改Item1为直接接收业务参数,不依赖父组件state
class Item1 extends StatelessWidget { const Item1({Key? key, required this.missionName}) : super(key: key); // 直接传递需要的文本参数,不和父组件耦合 final String missionName; @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( image: DecorationImage( image: AssetImage("assets/illustrations/ill_1.jpeg"), fit: BoxFit.cover, ), ), child: Column( children: <Widget>[ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children:[ Image( image:AssetImage("assets/images/leaf.png"), width: 8.0.w, ), Text( missionName, style:TextStyle( fontWeight: FontWeight.w500, fontFamily: 'Roboto', color: const Color(0xFFFFFFFF), fontSize: 15.0.sp ), ) ] ), Container(height: 20.0.h), Row( children: [ Text( "Dio Porco", style:TextStyle( fontWeight: FontWeight.w500, fontFamily: 'Roboto', color: const Color(0xFFFFFFFF), fontSize: 25.0.sp ), ) ] ) ], ), ), ] ), ); } }
第二步:新增加载状态,数据准备完成后再渲染幻灯片
给_HomePageState新增加载状态标记,加载过程中显示占位组件:
class _HomePageState extends State<HomePage> { List<String> MissionData1 = []; bool _isLoading = true; // 新增加载状态标记 Future<void> getMission1() async{ DocumentSnapshot snap = await widget.auth.MissionRetriever1(); Map<String,dynamic> data = snap.data(); setState(() { MissionData1.add(data['Q_Category']); MissionData1.add(data['Q_Name']); MissionData1.add(data['Q_Description']); MissionData1.add(data['Q_Score']); MissionData1.add(data['Q_Target']); _isLoading = false; // 数据加载完成修改状态 }); } // 在build方法中生成cardList时判断加载状态 @override Widget build(BuildContext context) { List<Widget> cardList; if (_isLoading) { // 加载中显示占位 cardList = [ Container( color: Colors.blueAccent, child: const Center(child: Text("加载中...", style: TextStyle(color: Colors.white))), ) ]; } else { cardList = [ // 把对应的数据传给Item1 Item1(missionName: MissionData1[1]), // 其他幻灯片项同理透传对应参数即可 ]; } // 原有页面布局逻辑保持不变 } }
方案2(不推荐,仅应急):创建Item1时传入当前state实例
如果你不想修改Item1的参数定义,只需要在生成cardList的时候把当前state实例传入即可:
cardList = [ Item1(homepage: this), // 其他幻灯片项 ];
该方案会导致子组件和父组件高度耦合,后续维护难度大,优先选择方案1。
内容的提问来源于stack exchange,提问作者Matteo Grondona
相关产品推荐
相关产品推荐

