RecyclerView加载指定前缀应用包数据不显示,请求排查问题
我帮你梳理几个关键问题,这些就是导致RecyclerView为空或显示异常的核心原因:
1. Android 11+ 包可见性限制(最可能的核心问题)
从Android 11(API 30)开始,系统引入了包可见性限制:默认情况下你的App只能访问自身、系统核心应用,以及在Manifest里明确声明过的第三方App。如果你的测试设备是Android 11或更高版本,直接调用getInstalledPackages根本拿不到com.google开头的大部分应用,自然RecyclerView就空了。
修复方法:
在AndroidManifest.xml里添加对应的权限或查询声明(二选一,优先选第二种更合规):
<!-- 方案1:获取所有已安装App的权限(Google Play上架需额外说明理由) --> <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" tools:ignore="QueryAllPackagesPermission" /> <!-- 方案2:精准声明仅访问com.google开头的包(推荐) --> <queries> <package android:name="com.google.*" /> </queries>
2. 获取应用名称的方式错误
你的PackageItem.getName()方法用了mPackageInfo.applicationInfo.name,这个字段对应的是Manifest里android:name属性(通常是Application类的全类名),不是用户看到的App显示名称,甚至很多App的这个字段是空的,会导致TextView显示空内容,看起来像RecyclerView没加载。
修复PackageItem类:
给PackageItem添加PackageManager引用,用正确的方式加载应用显示名称:
public class PackageItem { private PackageInfo mPackageInfo; private PackageManager mPm; // 新增PackageManager引用 // 修改构造方法,传入PackageManager public PackageItem(PackageInfo packageInfo, PackageManager pm) { mPackageInfo = packageInfo; mPm = pm; } public String getName() { // 用loadLabel获取用户可见的应用名称,为空时 fallback 到包名 return mPackageInfo.applicationInfo.loadLabel(mPm).toString(); } // 其他get方法保持不变 }
接着修改Adapter的构造方法,传入PackageManager:
public class PackageItemAdapter extends RecyclerView.Adapter<PackageItemAdapter.ViewHolder> { // ViewHolder内部类不变 private List<PackageItem> mPackages; // 修改构造方法,添加PackageManager参数 public PackageItemAdapter(List<PackageInfo> packages, PackageManager pm) { ArrayList<PackageItem> pis = new ArrayList<PackageItem>(); for(PackageInfo pkg : packages) { pis.add(new PackageItem(pkg, pm)); // 传入PackageManager } mPackages = pis; } // 其他重写方法保持不变 }
最后在MainActivity初始化Adapter时传入pm:
PackageItemAdapter adapter = new PackageItemAdapter(packages, pm);
3. 代码顺序小优化(非核心但更规范)
建议把setLayoutManager放在setAdapter之前,这是RecyclerView的常规使用顺序,同时可以去掉多余的adapter.notifyDataSetChanged()(刚初始化Adapter时数据已经就绪,不需要通知):
lstPackages.setLayoutManager(new LinearLayoutManager(this)); lstPackages.setAdapter(adapter);
4. 调试小技巧
可以在MainActivity里打印日志,确认是否真的筛选到了目标包:
Log.d("PKG", "总安装包数量:" + allPackages.size()); Log.d("PKG", "筛选后com.google包数量:" + packages.size());
如果packages.size()是0,那肯定是包可见性的问题;如果大于0但RecyclerView还是空,再排查Adapter或布局的问题。
内容的提问来源于stack exchange,提问作者Izaac Bränn

