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

Flutter侧滑删除列表项失效:热重启后已删项复现求助

解决Flutter笔记列表左滑删除后热重启恢复的问题

核心问题:你左滑删除笔记时,只修改了内存中的todoList,但没有把删除后的列表同步更新到SharedPreferences本地存储里。热重启后App会重新从本地读取旧的完整数据,所以删掉的项又会回来。

修复步骤:

  • 删除操作同步本地存储:在Dismissible的onDismissed回调里,删除列表项后立即把更新后的todoList存回SharedPreferences
  • 优化数据加载逻辑:原来的omLoadData用addAll会导致每次启动重复加载数据,改成直接赋值并清空旧列表
  • 避免Key冲突:如果有重复内容的笔记,用单一内容作为Dismissible的Key会引发异常,建议结合内容和索引生成唯一Key

修改后的关键代码片段:

1. 修复删除回调

onDismissed: (direction) async {
  setState(() {
    todoList.removeAt(index);
  });
  // 同步更新本地存储
  SharedPreferences prefs = await SharedPreferences.getInstance();
  await prefs.setStringList('todo_list', todoList);
},

2. 修复数据加载方法

void omLoadData() async {
  SharedPreferences prefs = await SharedPreferences.getInstance();
  final data = prefs.getStringList("todo_list");
  setState(() {
    todoList = data ?? []; // 为空时设空列表,避免空指针
  });
}

3. 修复Dismissible的Key

key: Key('${todoList[index]}-$index'),

完整修复后的代码

import 'dart:convert';
import 'dart:collection';
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:shared_preferences/shared_preferences.dart';

class Home extends StatefulWidget {
  const Home({key}) : super(key: key);

  @override
  State<Home> createState() => _HomeState();
}

class _HomeState extends State<Home> {
  final myController = TextEditingController();
  bool submit = false;

  Color mainColor = Color(0xFFEEEFF5);
  Color secColor = Color(0xFF3A3A3A);
  Color tdBlue = Color(0xFF5F52EE);

  String temp = "";
  List<String> todoList = [];
  String index = "";

  @override
  void initState() {
    super.initState();

    myController.addListener(() {
      setState(() {
        submit = myController.text.isNotEmpty;
      });
    });

    omLoadData();
  }

  submitData() async {
    setState(() {
      todoList.add(temp);
      clearText();
    });
    SharedPreferences prefs = await SharedPreferences.getInstance();
    await prefs.setStringList('todo_list', todoList);
  }

  void omLoadData() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    final data = prefs.getStringList("todo_list");
    setState(() {
      todoList = data ?? [];
    });
  }

  @override
  void dispose() {
    myController.dispose();
    super.dispose();
  }

  void clearText() {
    myController.clear();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: mainColor,
      appBar: AppBar(
        elevation: 0.0,
        backgroundColor: secColor,
        title: Text('ToDo - List',
            style: TextStyle(
                fontSize: 26.5,
                fontWeight: FontWeight.bold,
                fontStyle: FontStyle.italic)),
      ),
      body: Column(
        children: [
          Container(
            margin: EdgeInsets.only(top: 15.0, left: 13.0, right: 8.0),
            child: Row(
              children: [
                Expanded(
                  child: TextField(
                    onChanged: (String value) {
                      temp = value;
                    },
                    controller: myController,
                    decoration: InputDecoration(
                      prefixIcon: Icon(Icons.notes, color: Colors.orangeAccent),
                      labelText: 'Замітка',
                      hintText: 'Введіть замітку',
                      filled: true,
                      fillColor: Colors.white,
                      border: OutlineInputBorder(),
                      contentPadding: EdgeInsets.all(10.0),
                      enabledBorder: OutlineInputBorder(
                        borderRadius: BorderRadius.all(Radius.circular(30.0)),
                      ),
                    ),
                  ),
                ),
                SizedBox(width: 10.0),
                ElevatedButton(
                  style: ElevatedButton.styleFrom(backgroundColor: tdBlue),
                  onPressed: submit ? () => submitData() : null,
                  child: Text('+', style: TextStyle(fontSize: 35)),
                ),
              ],
            ),
          ),
          Expanded(
            child: Padding(
              padding: EdgeInsets.only(top: 5.0),
              child: ListView.builder(
                itemCount: todoList.length,
                itemBuilder: (BuildContext context, int index) {
                  final item = todoList[index];
                  return Dismissible(
                    direction: DismissDirection.endToStart,
                    background: const Card(
                      color: Colors.red,
                      child: Icon(Icons.delete_sweep, size: 30, color: Colors.white),
                    ),
                    key: Key('${todoList[index]}-$index'),
                    onDismissed: (direction) async {
                      setState(() {
                        todoList.removeAt(index);
                      });
                      SharedPreferences prefs = await SharedPreferences.getInstance();
                      await prefs.setStringList('todo_list', todoList);
                    },
                    child: Card(
                      margin: EdgeInsets.only(top: 8.5, left: 25.0, right: 25.0),
                      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(25.0)),
                      elevation: 0.0,
                      child: ListTile(
                        title: Text(todoList[index]),
                      ),
                    ),
                  );
                },
              ),
            ),
          ),
        ],
      ),
    );
  }
}

内容的提问来源于stack exchange,提问作者Назар Марцинко

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 17:15:54