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

Flutter中如何保存ReorderableListView的排序状态?

解决ReorderableListView排序重启后不保留的问题

你当前的代码只是在内存中调整了tasks列表的顺序,重启应用后内存数据会被重置,自然恢复成初始状态。而PageStorage的作用是保存页面的滚动位置、展开状态这类UI状态,并不负责持久化业务数据,所以用它没用。

要解决这个问题,核心是把排序后的列表数据持久化到本地存储,重启时再从本地读取恢复。下面是具体实现步骤:

1. 选择持久化方案

根据数据量大小选合适的方案:

  • 小数据量(比如几十条以内的简单列表):用SharedPreferences最方便
  • 复杂/大数据量:用Hive、SQLite或Isar这类数据库

下面以SharedPreferences为例演示。

2. 改造代码步骤

第一步:添加依赖

在pubspec.yaml里添加shared_preferences:

dependencies:
  flutter:
    sdk: flutter
  shared_preferences: ^2.2.2 # 可替换为最新版本

第二步:完整实现代码

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

class ReorderableListPage extends StatefulWidget {
  const ReorderableListPage({super.key});

  @override
  State<ReorderableListPage> createState() => _ReorderableListPageState();
}

class _ReorderableListPageState extends State<ReorderableListPage> {
  List<Map<String, dynamic>> tasks = [];

  @override
  void initState() {
    super.initState();
    _loadTasks(); // 初始化时从本地读取数据
  }

  // 从本地读取保存的任务列表
  Future<void> _loadTasks() async {
    final prefs = await SharedPreferences.getInstance();
    final tasksJson = prefs.getString('tasks');
    if (tasksJson != null) {
      setState(() {
        tasks = List<Map<String, dynamic>>.from(jsonDecode(tasksJson));
      });
    } else {
      // 本地无数据时初始化默认列表
      setState(() {
        tasks = [
          {'name': '任务1'},
          {'name': '任务2'},
          {'name': '任务3'},
        ];
      });
    }
  }

  // 将任务列表保存到本地
  Future<void> _saveTasks() async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.setString('tasks', jsonEncode(tasks));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('可拖拽排序列表')),
      body: ReorderableListView(
        physics: const ClampingScrollPhysics(),
        shrinkWrap: true,
        onReorder: (int oldIndex, int newIndex) {
          setState(() {
            if (newIndex > oldIndex) newIndex--;
            final item = tasks.removeAt(oldIndex);
            tasks.insert(newIndex, item);
          });
          _saveTasks(); // 排序完成后立即保存到本地
        },
        children: [
          for (final item in tasks)
            Container(
              key: ValueKey(item['name']), // 用唯一标识当key,避免Map类型key的不稳定问题
              margin: const EdgeInsets.symmetric(vertical: 4, horizontal: 16),
              child: ExpansionTile(
                title: Text(item['name']),
              ),
            )
        ],
      ),
    );
  }
}

关键说明

  • _loadTasks:页面初始化时从SharedPreferences读取之前保存的列表,无本地数据则加载默认值
  • _saveTasks:每次拖拽排序完成后,将新列表转成JSON字符串存入本地
  • ValueKey优化:原来用ValueKey(item)(item为Map)可能导致key不稳定,改用item内唯一字段(如name)更可靠

3. 复杂数据场景处理

如果你的tasks是自定义对象(而非Map),需要先为对象实现序列化/反序列化逻辑,比如使用json_serializable生成toJson/fromJson方法,再进行存储和读取。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 12:45:44