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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 12:43:15