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

如何在Dart的onInit()执行前优先加载List值?Flutter Sqlite开发问题

问题根因
  • 类实例化时会同步完成_questions属性的赋值,此时异步的Sqlite查询还未执行,savedList是空数组,所以_questions从一开始就是空的,后续savedList更新也不会触发_questions重新计算
  • GetX的onInit方法不会等待内部异步操作执行完成再推进页面渲染,等你拿到Sqlite查询结果时,页面已经完成首次渲染了
  • 你的Body组件是StatelessWidget,却声明了initState方法,该方法永远不会被执行,属于语法错误
修复步骤

第一步:修改QuestionController

  1. 把_questions改为响应式列表,新增加载状态标记,删除原有的固定初始化逻辑
  2. 调整onInit执行顺序,优先完成数据库查询、题目数据赋值,再初始化动画、页面控制器等业务逻辑
  3. 新增数据去重逻辑,避免每次进入页面重复插入相同题目

修改后的核心代码如下:

class QuestionController extends GetxController
    with SingleGetTickerProviderMixin {

  static Database _database;
  static DbConn dbConn = DbConn();

  AnimationController _animationController;
  Animation _animation;
  Animation get animation => this._animation;

  PageController _pageController;
  PageController get pageController => this._pageController;

  bool _isAnswered = false;
  bool get isAnswered => this._isAnswered;

  int _correctAns;
  int get correctAns => this._correctAns;

  int _selectedAns;
  int get selectedAns => this._selectedAns;

  RxInt _questionNumber = 1.obs;
  RxInt get questionNumber => this._questionNumber;

  int _numOfCorrectAns = 0;
  int get numOfCorrectAns => this._numOfCorrectAns;

  // 新增响应式题目列表和加载状态
  RxList<Question> _questions = <Question>[].obs;
  List<Question> get questions => _questions;
  RxBool isLoading = true.obs;

  @override
  Future<void> onInit() async {
    super.onInit();
    // 优先执行数据库操作
    String databasesPath = await getDatabasesPath();
    _database = await openDatabase(
      join(databasesPath, 'Question.db'),
      onCreate: (db, version) {
        debugPrint('called getQues inside DB table creation');
        return db.execute(
          "CREATE TABLE QuesTable(id INTEGER, question TEXT, options TEXT, answer_index INTEGER)",
        );
      },
      version: 1,
    );
    final Database db = _database;

    // 先查询表是否已有数据,避免重复插入
    List<Map> existingList = await db.rawQuery('SELECT * FROM QuesTable');
    if (existingList.isEmpty) {
      for (int i = 0; i < DbConn.sample_data.length; i++) {
        var exId = DbConn.sample_data[i]['id'];
        var exQuestion = DbConn.sample_data[i]['question'];
        var exOptions = DbConn.sample_data[i]['options'];
        var exAnswerIndex = DbConn.sample_data[i]['answer_index'];

        int insertId1 = await _database.rawInsert(
            'INSERT INTO QuesTable(id, question, options, answer_index) VALUES(?, ?, ?, ?)',
            [exId, exQuestion, exOptions, exAnswerIndex]
        );
        debugPrint('InsertedValue: $insertId1');
      }
      existingList = await db.rawQuery('SELECT * FROM QuesTable');
    }

    // 赋值题目列表
    _questions.value = existingList.map((question) => Question(
      id: question['id'],
      question: question['question'],
      options: question['options'],
      answer_index: question['answer_index']
    )).toList();

    // 数据加载完成后再初始化动画、页面控制器
    _animationController = AnimationController(duration: Duration(seconds: 30), vsync: this);
    _animation = Tween<double>(begin: 0, end: 1).animate(_animationController)
      ..addListener(() {
        update();
      });
    _pageController = PageController();

    // 标记加载完成
    isLoading.value = false;
    _animationController.forward().whenComplete(nextQuestion);
  }

  @override
  void onClose() {
    _animationController.dispose();
    _pageController.dispose();
    super.onClose();
  }

  // 其余原有方法checkAns、nextQuestion、updateTheQnNum、checkSavedlist保留即可
}

第二步:修改Body组件

  1. 删除无效的initState方法,若需要保留futureAlbum逻辑可以将Body改为StatefulWidget
  2. 新增加载状态判断,数据加载中显示加载动画,加载完成再渲染题目页面

修改后的核心代码如下:

class Body extends StatelessWidget{
  const Body({
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    QuestionController _questionController = Get.put(QuestionController());
    return Obx(() {
      // 加载中显示加载动画
      if (_questionController.isLoading.value) {
        return const Center(child: CircularProgressIndicator(color: kSecondaryColor));
      }
      // 加载完成显示原有页面
      return Stack(
        children: [
          SvgPicture.asset("assets/icons/endless-constellation.svg",
              fit: BoxFit.fill),
          SafeArea(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Padding(
                  padding:
                  const EdgeInsets.symmetric(horizontal: kDefaultPadding),
                  child: ProgressBar(),
                ),
                SizedBox(height: kDefaultPadding),
                Padding(
                  padding:
                  const EdgeInsets.symmetric(horizontal: kDefaultPadding),
                  child: Text.rich(
                    TextSpan(
                      text:
                      "Question ${_questionController.questionNumber.value}",
                      style: Theme.of(context)
                          .textTheme
                          .headline4
                          .copyWith(color: kSecondaryColor),
                      children: [
                        TextSpan(
                          text: "/${_questionController.questions.length}",
                          style: Theme.of(context)
                              .textTheme
                              .headline5
                              .copyWith(color: kSecondaryColor),
                        ),
                      ],
                    ),
                  ),
                ),
                Divider(thickness: 1.5),
                SizedBox(height: kDefaultPadding),
                Expanded(
                  child: PageView.builder(
                    physics: NeverScrollableScrollPhysics(),
                    controller: _questionController.pageController,
                    onPageChanged: _questionController.updateTheQnNum,
                    itemCount: _questionController.questions.length,
                    itemBuilder: (context, index) => QuestionCard(
                      question: _questionController.questions[index],
                    ),
                  ),
                ),
              ],
            ),
          )
        ],
      );
    });
  }
}

内容的提问来源于stack exchange,提问作者Terin Tittu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 04:54:03