我知道我可以捕获NameNotFoundException
from 调用PackageManager.getPackageInfo
或遍历PackageInfo
返回的列表PackageManager.getInstalledPackages
以了解是否安装了特定包,但这两者看起来要么冗长要么丑陋。在我的个人手机上,我安装了 300 多个软件包,所以我不想每次需要检查时都必须执行该操作。捕获异常作为执行应用程序逻辑的一种方式只会让我感觉整个人都错了。我是否在某处遗漏了 isPackageInstalled 方法,还是只需要使用上述技术之一自己实现它?如果是后者,哪个会被认为是更快和更少资源密集型的选择?
4 回答
由于PackageManager.getInstalledPackages()
返回 a List
,因此您无需手动循环遍历它。您可以使用List.contains()
或List.containsAll()
在一行代码中完成任务。当然,这不会改变效率,因为这两种方法本身都可能包含一个循环。
我编写了一些基准测试并测试了捕获异常与获取已安装包并循环它们的几种不同方法。这是我的结果
在所有情况下,无论是否安装了请求的包,调用 PackageManager.getPackageInfo 并捕获 NameNotFoundException 都需要 1 到 4 毫秒,并且我确保还包括首次调用 PackageManager 以执行特定应用程序的情况并作为后续调用,以防框架在每次应用启动时对这些信息进行任何缓存。
在所有情况下,调用 PackageManger.getPackageInfo 也需要 1 到 1.5 秒。
调用 getPackageInfo 并捕获异常以确定是否未安装包是迄今为止更快的检查方法。
处理 NameNotFoundExcepetion 不应该让你觉得“完全错了”恕我直言。根据文档,如果自 api 级别 1 起包不存在,则会引发此异常。使用 try/catch 语句与使用 if/then 语句测试空值非常相似。
在这种情况下,不应将其视为解决方法或 hack,因为您正在使用记录在案的和预期的异常返回值来确定包是否存在。
我认为这种方法比遍历 getInstalledPackages() 返回的列表要快。但是,我不知道 android 在返回 NameNotFoundExcepetion 之前采取了哪些步骤。这将是一个有趣的基准测试。
我不知道有任何其他实用的方法来测试已安装的包。