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

GetX无法更新界面列表求助:笔记应用数据已获取却不显示

问题描述

开发简易笔记应用,笔记数据从localhost后端获取。登录后导航至notes_screen.dart时,笔记数据已成功获取并添加到列表,但应用界面不显示笔记;热重载后列表能正常显示。

日志显示:控制器初始化后先检测到列表为空,后端响应返回后数据存入列表,但界面未触发更新。


NotesScreen 代码

import 'package:flutter/material.dart';
import 'package:flutter_lorem/flutter_lorem.dart';
import 'package:get/get.dart';
import 'package:logging/logging.dart';
import 'package:notes_app/controllers/login_controller.dart';
import 'package:notes_app/controllers/notes_controller.dart';
import 'package:notes_app/screens/empty_state_screen.dart';
import 'package:notes_app/screens/notes/note_viewer_screen.dart';

import '../../widgets/note_card.dart';
import 'new_note.dart';

class NotesPage extends GetWidget<NotesController> {
  final log = Logger("NotesPage");

  NotesPage({super.key});

  LoginController loginController = Get.find<LoginController>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
     // some code 
      body: Obx(
        () => controller.isNotesListEmpty()
            ? const Center(child: EmptyState())
            : Padding(
                padding: const EdgeInsets.all(8.0),
                child: ListView.builder(
                    itemCount: controller.notesList.value.length,
                    itemBuilder: (context, index) {
                      return Dismissible(
                        key: UniqueKey(),
                        secondaryBackground: Container(
                          color: Colors.red,
                          child: const Center(
                            child: Icon(Icons.delete_forever),
                          ),
                        ),
                        background: Container(color: Colors.red),
                        onDismissed: (direction) {
                          controller
                              .deleteNote(controller.notesList.value[index].id);
                        },
                        child: NoteCard(
                          note: controller.notesList.value[index],
                          onTap: () async {
                            Get.to(() => NoteViewer(),
                                arguments: controller.notesList.value[index]);
                          },
                          onLongPress: () async {
                            showDialog(
                              context: context,
                              builder: (context) {
                                return AlertDialog(
                                  title: Text('delete_msg'.tr),
                                  actions: [
                                    TextButton(
                                      onPressed: () {
                                        controller.deleteNote(controller
                                            .notesList.value[index].id);
                                      },
                                      child: Text('yes'.tr),
                                    ),
                                    TextButton(
                                      onPressed: () {
                                        Get.back();
                                      },
                                      child: Text('no'.tr),
                                    ),
                                  ],
                                );
                              },
                            );
                          },
                        ),
                      );
                    }),
              ),
      ),
    // some code
    );
  }
}

NotesController 代码

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:logging/logging.dart';
import 'package:notes_app/models/new_note_model.dart';
import 'package:notes_app/models/note_model.dart';
import 'package:notes_app/screens/notes/home_screen.dart';
import 'package:notes_app/services/rest_apis.dart';

class NotesController extends GetxController {
  final log = Logger("NotesController");
  Rx<List<Note>> notesList = Rx<List<Note>>([]);
  var titleController = TextEditingController();
  var contentController = TextEditingController();
  RestAPIs restAPI = Get.find<RestAPIs>();

  @override
  void onInit() {
    super.onInit();
    getAllNotes();
    ever(notesList, (callback) => null);
  }

  @override
  void onClose() {
    log.fine("The controller has been deleted");
  }

  bool isNotesListEmpty() {
    if (notesList.value.isEmpty) {
      log.warning("The list notes is Empty!");
      return true;
    } else {
      log.fine("The list notes is not Empty!");
      return false;
    }
  }

  Future getAllNotes() async {
    var results = await restAPI.fetchAllNotes();
    List<Note> notes = List.generate(
      results.length,
      (index) => Note.fromJson(results[index]),
    );
    log.info("The length of the notesList ${notes.length.toString()}");
    notesList.value.addAll(notes);
  }
}

应用运行日志

[GETX] Instance "NotesController" has been created
[GETX] Instance "NotesController" has been initialized
I/flutter ( 4179): WARNING: 2023-10-15 04:58:45.435093: The list notes is Empty!
I/flutter ( 4179): INFO: 2023-10-15 04:58:45.577467: The length of the notesList 10

问题分析与修复

核心原因

GetX的Rx<List<T>>仅在列表引用被替换时才会通知UI刷新。调用addAll()只是修改了原有列表的内容,没有改变列表的引用,因此Obx监听不到变化,界面不会更新。热重载时会重新构建Widget,此时能读取到最新的列表内容,所以显示正常。

修复方法

修改getAllNotes()方法,通过替换列表引用来触发Rx更新:

Future getAllNotes() async {
  var results = await restAPI.fetchAllNotes();
  List<Note> notes = List.generate(
    results.length,
    (index) => Note.fromJson(results[index]),
  );
  log.info("The length of the notesList ${notes.length.toString()}");
  // 直接替换整个列表,触发UI更新
  notesList.value = notes;
}

如果需要保留原有列表数据并追加新数据,可以使用展开运算符创建新列表:

notesList.value = [...notesList.value, ...notes];

另外,控制器中ever(notesList, (callback) => null)这段代码没有实际作用,建议删除。


内容的提问来源于stack exchange,提问作者Omer Elkhalifa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 07:40:57