Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/356.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 更快速、更干净地了解Android上是否安装了软件包_Java_Android - Fatal编程技术网

Java 更快速、更干净地了解Android上是否安装了软件包

Java 更快速、更干净地了解Android上是否安装了软件包,java,android,Java,Android,我知道我可以通过调用PackageManager.getPackageInfo捕获NameNotFoundException,或者通过PackageManager.getInstalledPackages返回的PackageInfo列表循环,以了解是否安装了特定的包,但这两种方法似乎都很冗长或难看。在我的个人电话上,我安装了300多个软件包,所以我不想每次需要检查时都要进行这种操作。捕捉异常作为执行应用程序逻辑的一种手段,只会让我觉得自己完全错了。我是否在某个地方遗漏了isPackageInst

我知道我可以通过调用
PackageManager.getPackageInfo
捕获
NameNotFoundException
,或者通过
PackageManager.getInstalledPackages
返回的
PackageInfo
列表循环,以了解是否安装了特定的包,但这两种方法似乎都很冗长或难看。在我的个人电话上,我安装了300多个软件包,所以我不想每次需要检查时都要进行这种操作。捕捉异常作为执行应用程序逻辑的一种手段,只会让我觉得自己完全错了。我是否在某个地方遗漏了isPackageInstalled方法,或者我是否只需要使用上述技术之一自己实现它?如果是后者,哪一种会被认为是更快、更少的资源密集型选择?

处理NameNotFoundException不应该让你觉得“到处都是错的”。根据api级别1,如果包不存在,则将引发此异常。使用try/catch语句与使用if/then语句测试空值非常相似

在这种情况下,不应将其视为解决方法或黑客行为,因为您正在使用异常的记录和预期返回值来确定包是否存在

我假设此方法比遍历getInstalledPackages()返回的列表更快。然而,我不知道android在返回NameNotFoundException之前采取了什么步骤。这将是一个有趣的基准测试


我不知道有任何其他实用的方法来测试已安装的软件包。

由于返回一个
列表
,您不需要手动循环。您可以使用或在一行代码中完成任务。当然,这不会改变效率,因为这两种方法本身都可能包含一个循环。

如果使用API真的有问题,那么您可能会研究涉及以下内容的黑客行为

获取PM列表的Bash shell表达式 Java运行时表达式 Java管道、缓冲区和流 Java NIO Java grep

所以bash表达式应该是:

pm列表包-f | sed的/^包。/'| awk-f“=“{print$2”“$1}”排序

以及从“pm列表”中处理标准输出的引用列表,其方式可能会更快


我编写了一些基准测试,并测试了捕获异常与获取已安装软件包并在其中循环的几种不同方法。这是我的结果

  • 无论请求的包是否安装,调用PackageManager.getPackageInfo并捕获NameNotFoundException都需要1到4毫秒,我还确保包括以下情况,即这是针对特定应用程序运行的第一次调用PackageManager,以及后续调用,以防框架在每次应用程序启动时缓存这些信息

  • 在所有情况下,调用PackageManger.getPackageInfo也需要1到1.5秒


  • 调用getPackageInfo并捕获异常以确定包是否未安装是目前最快的检查方法。

    甚至有意将空结果转换为异常。@zapl我知道!在拍我的手腕之前,至少让我检查一下空值。我强烈反对。抛出异常的操作不仅代价昂贵而且速度慢,而且很难看,不能表达我的意图。您应该阅读以下页面上的一些讨论:。至于循环,就CPU周期而言,即使大约300次迭代也没有那么昂贵,昂贵的部分是getInstalledPackages调用的内部内容。@Rich这是一个很好的链接。我认为你应该把它作为你问题的参考。这正是我所建议的那种基准,我说我不知道抛出异常的内部过程。话虽如此,安卓团队似乎确实打算这样使用它。因此,它不应该被认为是脏的。我喜欢您的逻辑,但是List.contains会接受一个PackageInfo类型的对象并进行引用比较,而不仅仅是检查packageName属性是否相等,这正是我真正需要的。我确信它们是在内部循环的,所以就性能而言,它可能等于我自己做的。在C#中,我可以向方法传递一个lambda表达式来描述我首选的比较逻辑,但据我所知,Java没有这种功能。Collections.binarySearch()如何,它允许您提供一个比较器?当然,您必须首先对列表进行排序…它看起来很酷,但排序实际上使它比循环慢了约6倍,我在没有终止条件的情况下测试了循环,以便可以测量最坏的情况。尽管如此,昂贵的部分首先只是向系统索要软件包。看来没有好的答案。抓捕前任似乎是安卓系统作者推荐的方法。谢谢你的帮助