Flutter文件管理器:如何同时按大小排序文件与文件夹?
解决Flutter文件管理器文件与文件夹按大小共同排序的问题
你当前的问题核心是:排序时文件夹用的是目录自身的元数据大小(通过stat()获取的size,一般只有几KB),而非文件夹内所有文件的总大小,所以看起来文件夹没按实际内容大小排序。要实现文件和文件夹按真实大小排序,需要先预计算文件夹的总内容大小,再用这个值参与排序逻辑。
步骤1:实现文件夹总大小计算方法
先写一个可以计算文件夹所有内容总大小的方法,为了避免UI卡顿,用异步+隔离线程处理:
// 异步计算文件夹总大小,放在隔离线程执行 Future<int> calculateFolderTotalSize(Directory dir) async { return compute(_computeFolderSize, dir.path); } // 实际计算逻辑,运行在隔离线程 int _computeFolderSize(String folderPath) { int totalSize = 0; try { final directory = Directory(folderPath); // 递归遍历所有子文件和文件夹 final entities = directory.listSync(recursive: true); for (final entity in entities) { if (entity is File) { totalSize += entity.lengthSync(); } } } catch (e) { // 处理权限不足或无法访问的情况,返回0 return 0; } return totalSize; }
步骤2:修改排序逻辑,加入文件夹大小计算
假设你有一个文件列表List<FileSystemEntity> fileList,修改onlySortSize方法,先预计算所有文件夹的大小并缓存,再统一排序:
Future<void> onlySortSize() async { // 缓存文件夹大小,避免重复计算 final Map<String, int> folderSizeCache = {}; // 收集所有文件夹,并行计算大小 final folders = fileList.whereType<Directory>().toList(); await Future.wait(folders.map((dir) async { final size = await calculateFolderTotalSize(dir); folderSizeCache[dir.path] = size; })); // 执行排序:文件取自身大小,文件夹取缓存的总大小 fileList.sort((a, b) { int sizeA = 0; if (a is File) { sizeA = a.lengthSync(); } else if (a is Directory) { sizeA = folderSizeCache[a.path] ?? 0; } int sizeB = 0; if (b is File) { sizeB = b.lengthSync(); } else if (b is Directory) { sizeB = folderSizeCache[b.path] ?? 0; } // 升序排序,要降序就改成 sizeB.compareTo(sizeA) return sizeA.compareTo(sizeB); }); // 通知控制器更新UI controller.sortBy(SortBy.size); controller.notifyListeners(); }
步骤3:优化UI显示的文件夹大小
把排序时缓存的文件夹大小传给folderSize组件,避免重复计算:
Widget folderSize(FileSystemEntity entity, Map<String, int>? sizeCache) { if (entity is File) { return Text(FileManager.formatBytes(entity.lengthSync())); } else if (entity is Directory) { // 优先用缓存的大小 final cachedSize = sizeCache?[entity.path]; if (cachedSize != null) { return Text(FileManager.formatBytes(cachedSize)); } // 没有缓存时异步计算 return FutureBuilder<int>( future: calculateFolderTotalSize(entity as Directory), builder: (context, snapshot) { if (snapshot.hasData) { return Text(FileManager.formatBytes(snapshot.data!)); } else if (snapshot.hasError) { return const Text('无法获取大小'); } return const Text('计算中...'); }, ); } return const Text('-'); }
关键说明
- 不要用
Directory.stat().size作为文件夹的排序依据:这个值是目录本身的磁盘占用(仅元数据,一般4KB左右),不是文件夹内容的总大小。 - 缓存文件夹大小:大文件夹计算耗时,缓存可以避免重复计算,提升性能。
- 异步+隔离线程:避免计算大文件夹时UI卡顿,
compute函数会自动把计算逻辑放到后台线程。
内容的提问来源于stack exchange,提问作者Mert Ünal
相关产品推荐
相关产品推荐

