Flutter问答应用导航卡顿求助:问题列表加载耗时3-4秒
解决Flutter Quiz应用导航卡顿问题
问题根源
你遇到的导航卡顿是因为在点击分类时同步创建并传递200+条QuestionCategory数据,这会阻塞主线程:Navigator.push的builder回调会同步初始化目标页面,而传递大列表+页面渲染的同步操作会占用大量主线程资源,导致卡顿3-4秒。
解决方案
1. 传递分类标识而非完整列表(最优方案)
不要直接传递整个问题列表,改为传递分类ID/名称,在目标页面内部异步加载对应数据。这样导航时仅传递少量数据,主线程不会被阻塞。
修改CategoryWiseScreen的点击逻辑:
onTapHandler: () { Navigator.push( context, CupertinoPageRoute( builder: ((context) => CategoryQuestion( title: category[index], categoryName: category[index], // 仅传递分类名称 )), ), ); }
修改CategoryQuestion页面,异步加载数据:
class CategoryQuestion extends StatefulWidget { final String title; final String categoryName; const CategoryQuestion({ Key? key, required this.title, required this.categoryName, }) : super(key: key); @override State<CategoryQuestion> createState() => _CategoryQuestionState(); } class _CategoryQuestionState extends State<CategoryQuestion> { late Future<List<QuestionCategory>> _questionsFuture; @override void initState() { super.initState(); // 异步加载对应分类的问题(实际可从本地JSON、SQLite或Assets读取) _questionsFuture = _loadQuestions(); } Future<List<QuestionCategory>> _loadQuestions() async { // 模拟IO延迟,实际替换为真实数据加载逻辑 await Future.delayed(const Duration(milliseconds: 100)); // 根据分类名称返回对应问题列表 if (widget.categoryName == 'River') { return List.generate(200, (i) => QuestionCategory( question: 'River Question $i', correctAnswer: 'Answer $i', )); } return []; } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text(widget.title)), body: FutureBuilder<List<QuestionCategory>>( future: _questionsFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); // 加载提示 } else if (snapshot.hasError) { return const Center(child: Text('加载失败')); } else if (snapshot.data!.isEmpty) { return const Center(child: Text('暂无问题')); } // 用ListView.builder懒加载问题项 return ListView.builder( itemCount: snapshot.data!.length, itemBuilder: (context, index) { return ListTile( title: Text(snapshot.data![index].question), subtitle: Text(snapshot.data![index].correctAnswer), ); }, ); }, ), ); } }
2. 提前预加载所有分类数据
如果数据量不大且常驻内存,可以在CategoryWiseScreen初始化时提前加载所有分类的问题列表,避免点击时临时创建。
将CategoryWiseScreen改为StatefulWidget并预加载数据:
class CategoryWiseScreen extends StatefulWidget { const CategoryWiseScreen({Key? key}) : super(key: key); @override State<CategoryWiseScreen> createState() => _CategoryWiseScreenState(); } class _CategoryWiseScreenState extends State<CategoryWiseScreen> { late Map<String, List<QuestionCategory>> _allCategoryQuestions; @override void initState() { super.initState(); // 提前加载所有分类数据(可放在异步任务中避免阻塞页面初始化) _allCategoryQuestions = { 'River': List.generate(200, (i) => QuestionCategory( question: 'River Question $i', correctAnswer: 'Answer $i', )), // 其他分类数据 }; } @override Widget build(BuildContext context) { var category = ['River']; return Scaffold( // 原页面结构保留 body: AnimationLimiter( child: ListView.builder( // 移除cacheExtent:9999999,避免强制缓存所有列表项占用内存 itemCount: category.length, itemBuilder: (context, index) { return AnimationConfiguration.staggeredList( position: index, duration: const Duration(milliseconds: 375), child: SlideAnimation( verticalOffset: 50.0, child: FadeInAnimation( child: Column( children: <Widget>[ SubCategoryTiles( categoryIcon: Icons.school, titleText: Center( child: Text( category[index], style: headingTextStyle, textAlign: TextAlign.center, ), ), onTapHandler: () { Navigator.push( context, CupertinoPageRoute( builder: ((context) => CategoryQuestion( title: category[index], questionCategory: _allCategoryQuestions[category[index]]!, )), ), ); }, ), const Divider(), ], ), ), ), ); }, ), ), ); } }
3. 额外优化点
- 移除
cacheExtent:9999999:该参数会强制ListView缓存所有列表项,导致内存占用过高,加重主线程负担。 - 简化动画:如果
flutter_staggered_animations的动画对性能有影响,可以尝试简化或移除,改用默认的淡入/滑动效果。 - 目标页面使用懒加载:确保CategoryQuestion页面用
ListView.builder渲染问题,而非一次性创建所有Widget。
内容的提问来源于stack exchange,提问作者Mahender Kumar
相关产品推荐
相关产品推荐

