Android 不同流程中的服务

Android 不同流程中的服务,android,Android,我的应用程序显示大量图像并将其缓存在内存中,因此它使用了大量内存(接近40MB的堆大小)。另一方面,它下载大的7zip文件(300MB)并使用本机代码提取它们,本机代码使用大量内存和处理。有时提取无法完成,但在应用程序进程重新启动后,它会工作。虽然我没有得到任何异常,因为它是本机代码,但我相信这是因为内存不足 所以我决定将提取放在不同的进程中,这样我可以在提取完成后将其终止(这里新进程的成本不是问题,因为首先任务更重要,提取本身占用大量处理器)。但是现在,在结束这个过程之前,我必须检查是否还没有

我的应用程序显示大量图像并将其缓存在内存中,因此它使用了大量内存(接近40MB的堆大小)。另一方面,它下载大的7zip文件(300MB)并使用本机代码提取它们,本机代码使用大量内存和处理。有时提取无法完成,但在应用程序进程重新启动后,它会工作。虽然我没有得到任何异常,因为它是本机代码,但我相信这是因为内存不足

所以我决定将提取放在不同的进程中,这样我可以在提取完成后将其终止(这里新进程的成本不是问题,因为首先任务更重要,提取本身占用大量处理器)。但是现在,在结束这个过程之前,我必须检查是否还没有开始另一次提取。我想到了两个解决方案:

1-为每次提取启动一个全新的过程。(我不知道这在android中是否可行)

2-以某种方式检查是否未启动另一次提取,如果未启动,则终止该过程。(可能会再次导致内存不足)

3-在开始新的提取之前,以某种方式等待提取完成。(这是非常复杂的,因为它必须在不同的过程之间完成)

因为我不知道怎么做,我真的需要专家的建议

--编辑-----------------------------------------------

我检查了提取一个400MB的7zip文件。在第一次提取之后,它总是失败。因此,每次提取后必须终止该过程,并启动一个新的提取过程。因此,第二个选项不在列表中


作为记录,本机7zip代码不是我的,它是基于linux的7ZA的Andro7Z,即使我自己编译了它,但我真的不想弄乱它。

好吧,如果你真的必须的话……你可以把你的提取放在
服务
中,把
服务
放在一个单独的过程中

一次只允许进行一次提取(您可以自己控制)。如果您使用
startService()
启动提取,Android将确保您只运行一个
服务
实例。在
onStartCommand()
中,您应该检查您是否已经进行了提取,如果已经进行了提取,您可以拒绝请求或将其排入数据库或其他任何地方。如果没有,则启动一个新线程来执行提取


一旦提取完成,该过程可能会自杀。下一次尝试提取(使用
startService()
)将导致Android创建一个新进程,并启动
服务的一个新实例,如果我很清楚您试图提取一些文件。我将只考虑Android代码,提取器代码可能包含内存泄漏

但是您可以使用AsyncTask类将此过程置于后台,并在完成后接收回调。此外,如果您需要跟踪提取任务,还可以使用任务实例列表,这样您就可以控制它们,确切地知道有多少仍在运行,或者取消它们

因此,我将创建如下内容:

ExtractTaskController—负责创建、管理和保存对任务的引用。
ExtractAsyncTask—扩展AsyncTask类,并执行实际提取。

您可以将提取服务放在单独的进程中,但为什么要在完成后终止它?如果您已经正确编程,它应该能够回收它使用的所有内存。若并没有,那个么你们需要修复它,而不是寻找解决代码泄漏的方法。有多少用户希望他们的手机内存有漏洞?@DavidWasser实际上7zip本地代码不是我的。它是基于linux的7za的Andro7z。我更喜欢在事后杀死它,这样就可以完全回收内存。我还没有检查它,但是如果第二个摘录没有得到足够的内存呢。另一方面,这是我最后一个也是最可靠的选择,因为一次不会有两个或多个提取。要么你没有在库中调用正确的方法来释放内存,要么库有内存泄漏。你应该和创建这个库的人谈谈。如果它是在IntentService中创建的呢?IntentService是只限于一个实例还是可以多个实例?另一个问题,是否有办法检查服务是否正在运行,并在发送新的intent之前以某种方式等待它完成?所有Android服务只存在一次。安卓帮你管理。是的,我查过了。IntentService将请求排队。请阅读我的编辑。非常感谢。您可以使用
ActivityManager.getRunningServices()
检查您的服务是否正在运行。但是,这并不是一个很好的方法(文档不鼓励将其用于非调试目的)。另一个选择是绑定到服务并询问它是否忙。文件类型是7Z,android不支持。这些文件很大,所以Java7z无法提取它们。所以它必须使用本机代码来完成。@Ali正如我所说的,您可以将本机调用放在AsyncTask中,在它完成后,您可以释放您使用的资源。如果希望一次执行一个,还可以在控制器中实现堆栈。我无法控制本机库,因此无法释放资源。所以我决定加入不同的进程。AsyncTask有一个定义良好的生命周期,它将生成不同的进程,执行任务,执行清理(将实例设置为null,关闭套接字等),并且在应用程序的同一进程上运行,它在不同的线程中运行。