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

Flutter本地存储数据不显示问题:showModalBottomSheet输入数据无法在首页ListView中展示

问题排查与解决方案

首先咱们来拆解下你遇到的核心问题:点击保存后数据没在首页ListView显示,本质是首页没感知到数据更新,再加上几处代码逻辑的小问题,导致数据流转不通。

一、核心问题分析

1. FutureBuilder 不会自动刷新数据

你首页用的FutureBuilder依赖storage.ready这个Future,它只会在页面初始化时执行一次。当你在BottomSheet里把数据存到本地后,storage.ready已经完成了,不会再次触发FutureBuilder重新构建,所以新数据根本不会被读取并展示。

2. 保存后没触发首页状态更新

你在BottomSheet的保存按钮里调用了setState,但这个setState要么是BottomSheet内部的(因为用了StatefulBuilder),要么就算是外层页面的,也没让首页的列表重新读取最新的存储数据。

3. 数据保存逻辑的衔接漏洞

你的保存按钮里调用了_save(),但你提供的本地存储函数是_addReminder,如果_save()里没有正确把输入框的nameController.text和detailsController.text传给_addReminder,那数据根本没被添加到列表和存储里。

4. SnackBar 上下文无效

你在Navigator.pop(context)之后调用ScaffoldMessenger.of(context).showSnackBar,这里的context是BottomSheet的上下文,pop之后它已经脱离Widget树了,SnackBar大概率不会正常显示。

二、分步解决方案

1. 让首页能实时获取最新数据

方案A:用状态管理自动监听变化(推荐)

把列表数据改成用ChangeNotifier管理,这样新增数据时自动通知首页刷新:

class ReminderManager extends ChangeNotifier {
  List<Data> items = [];
  final Storage storage;
  int id = 0;

  ReminderManager(this.storage) {
    _loadFromStorage();
  }

  Future<void> _loadFromStorage() async {
    await storage.ready;
    final storedItems = storage.getItem('reminder');
    if (storedItems != null) {
      items = List<Data>.from((storedItems as List).map((item) => Data(
            id: item['id'],
            name: item['name'],
            details: item['details'],
            save: item['save'],
          )));
      id = items.isNotEmpty ? items.last.id + 1 : 0;
    }
    notifyListeners();
  }

  void addReminder(String name, String details) {
    final newItem = Data(id: id, name: name, details: details, save: true);
    items.add(newItem);
    id++;
    _saveToStorage();
    notifyListeners(); // 通知所有监听者刷新
  }

  Future<void> _saveToStorage() async {
    await storage.ready;
    await storage.setItem('reminder', items.map((e) => {
      'id': e.id,
      'name': e.name,
      'details': e.details,
      'save': e.save
    }).toList());
  }
}

然后在首页用Consumer包裹列表:

Consumer<ReminderManager>(
  builder: (context, manager, child) {
    return ListView.builder(
      itemExtent: 50.0,
      itemCount: manager.items.length,
      itemBuilder: (context, index) {
        final item = manager.items[index];
        return remindersCard(item.name, item.details);
      },
    );
  },
)

方案B:手动触发首页刷新

打开BottomSheet时用await等待关闭,然后调用首页的setState重新读取数据:

// 打开BottomSheet的代码
await showModalBottomSheet(
  useRootNavigator: true,
  context: context,
  clipBehavior: Clip.antiAlias,
  shape: RoundedRectangleBorder(
    borderRadius: BorderRadius.vertical(top: Radius.circular(24)),
  ),
  builder: (context) {
    // 你的BottomSheet内容
  },
);
// BottomSheet关闭后,手动刷新首页状态
setState(() {});

同时修改首页的FutureBuilder逻辑,每次构建都重新读取存储:

Future<List<Data>> _getLatestReminders() async {
  await storage.ready;
  final storedItems = storage.getItem('reminder');
  if (storedItems == null) return [];
  return List<Data>.from((storedItems as List).map((item) => Data(
        id: item['id'],
        name: item['name'],
        details: item['details'],
        save: item['save'],
      )));
}

// 首页的ListView部分
FutureBuilder<List<Data>>(
  future: _getLatestReminders(),
  builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.waiting) {
      return Center(child: CircularProgressIndicator());
    }
    final reminders = snapshot.data ?? [];
    return ListView.builder(
      itemExtent: 50.0,
      itemCount: reminders.length,
      itemBuilder: (context, index) {
        return remindersCard(reminders[index].name, reminders[index].details);
      },
    );
  },
)

2. 修正BottomSheet的保存逻辑

  • 确保_save()正确传递输入框的值:
void _save() {
  final name = nameController.text.trim();
  final details = detailsController.text.trim();
  _addReminder(name, details); // 把输入值传给存储函数
}
  • 修复SnackBar的上下文问题:
ElevatedButton(
  onPressed: () {
    if (_formKey.currentState!.validate()) {
      _save();
      // 先显示SnackBar再关闭BottomSheet
      ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Done')));
      Navigator.pop(context);
    }
  },
  child: Text('save'),
)

3. 正确使用StatefulBuilder的状态更新

如果BottomSheet里需要更新输入验证状态,要用StatefulBuilder提供的setModalState,而不是外层页面的setState:

StatefulBuilder(builder: (context, setModalState) {
  return Container(
    padding: const EdgeInsets.all(32),
    child: Form(
      key: _formKey,
      child: Column(
        children: [
          TextFormField(
            validator: (value) => value!.isEmpty ? 'Please enter name' : null,
            controller: detailsController,
            style: TextStyle(),
            border: OutlineInputBorder(borderRadius: BorderRadius.circular(5.0)),
          ),
          // 第二个TextFormField...
          SizedBox(height: 10),
          ElevatedButton(
            onPressed: () {
              setModalState(() {
                if (_formKey.currentState!.validate()) {
                  _save();
                  ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Done')));
                  Navigator.pop(context);
                }
              });
            },
            child: Text('save'),
          )
        ],
      ),
    ),
  );
})

总结

最关键的就是让首页能感知到数据变化——要么用状态管理自动通知,要么手动触发刷新。同时检查数据保存的链路,确保输入框的内容确实被传到了存储函数里。

内容的提问来源于stack exchange,提问作者Abrar Lasebai

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 15:47:47