如何快速排序Android的ApplicationInfo列表:用户应用优先并缩短耗时
Android ApplicationInfo 排序优化方案
原排序代码耗时超5秒的核心问题是排序比较阶段重复调用loadLabel()——这个方法需要读取应用资源文件,属于IO密集型操作,排序时会被触发O(n log n)次,导致大量冗余耗时。以下是针对性的优化方案:
优化思路
- 预缓存排序依赖数据:提前把每个应用的「系统/用户标记」和「应用标签」计算并缓存,避免排序时重复计算/加载。
- 简化排序阶段的比较逻辑:直接使用缓存好的数据进行比较,减少排序时的计算开销。
优化后代码示例
第一步:定义辅助缓存类
先创建一个辅助类,存储排序时需要的所有字段,避免重复计算:
static class AppSortCache { ApplicationInfo appInfo; boolean isSystemApp; String appLabel; AppSortCache(ApplicationInfo app, PackageManager pm) { this.appInfo = app; // 一次性计算系统应用标记 this.isSystemApp = (app.flags & ApplicationInfo.FLAG_SYSTEM) == ApplicationInfo.FLAG_SYSTEM; // 一次性加载应用标签,避免重复调用loadLabel() CharSequence label = app.loadLabel(pm); this.appLabel = label != null ? label.toString() : app.packageName; } }
第二步:预缓存+排序
将原列表转换为缓存列表后再排序,最后按需还原为原类型列表:
// 1. 预缓存所有应用的排序依赖数据 List<AppSortCache> cacheList = new ArrayList<>(originalList.size()); for (ApplicationInfo app : originalList) { cacheList.add(new AppSortCache(app, packageManager)); } // 2. 对缓存列表进行排序 cacheList.sort((cache1, cache2) -> { // 先区分用户应用/系统应用的顺序 if (!cache1.isSystemApp && cache2.isSystemApp) { return -1; // 用户应用排前面 } if (cache1.isSystemApp && !cache2.isSystemApp) { return 1; // 系统应用排后面 } // 同类型应用按标签忽略大小写排序 return cache1.appLabel.compareToIgnoreCase(cache2.appLabel); }); // 3. (可选)还原为ApplicationInfo列表 List<ApplicationInfo> sortedList = new ArrayList<>(originalList.size()); for (AppSortCache cache : cacheList) { sortedList.add(cache.appInfo); }
优化效果说明
- 核心耗时优化:
loadLabel()从被调用O(n log n)次减少到n次,直接消除了重复资源加载的巨大开销,排序耗时可从5秒级降到几百毫秒以内。 - 减少重复计算:系统应用标记只计算一次,避免排序时重复位运算。
- 排序效率提升:使用
List.sort()(Java 8+)比原代码的Collections.sort()更高效,因为它直接操作列表内部数组,减少中间对象创建。
额外优化建议
- 如果不需要保留原列表,可以直接使用
cacheList中的appInfo,省去还原步骤。 - 若应用数量极大(≥500),可尝试并行排序,但Android平台上需测试线程开销是否划算,一般预缓存已足够满足需求。
内容的提问来源于stack exchange,提问作者OMAR_HYDR
相关产品推荐
相关产品推荐

