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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 10:40:37