Android 如果存在';异步任务已在运行

Android 如果存在';异步任务已在运行,android,android-asynctask,Android,Android Asynctask,当用户登录到我的应用程序时。我正在启动一个asynctask任务来维护用户会话。异步任务将无限期运行,直到用户注销。我的问题是,当我尝试启动其他asynctasks时,它们的doInBackground()方法永远不会执行 我在某处读到,如果异步任务已经在运行,我们就不能启动新的异步任务。我可以确认这一点,因为当我删除用户会话异步任务时,它工作正常。有解决办法吗 注意:我已经使用了executeOnExecutor()方法。但是它没有帮助。如果您是为API 11或更高版本开发的,您可以使用Asy

当用户登录到我的应用程序时。我正在启动一个
asynctask
任务来维护用户会话。异步任务将无限期运行,直到用户注销。我的问题是,当我尝试启动其他
asynctasks
时,它们的
doInBackground()
方法永远不会执行

我在某处读到,如果异步任务已经在运行,我们就不能启动新的
异步任务
。我可以确认这一点,因为当我删除用户会话异步任务时,它工作正常。有解决办法吗


注意:我已经使用了
executeOnExecutor()
方法。但是它没有帮助。

如果您是为API 11或更高版本开发的,您可以使用
AsyncTask.executeOnExecutor()
允许同时运行多个AsyncTask


对于可能长时间运行的操作,我建议您使用
服务
,而不是
异步任务

当用户登录时启动服务

Intent i= new Intent(context, YourService.class);
i.putExtra("KEY1", "Value to be used by the service");
context.startService(i); 
并在用户注销时停止服务

stopService(new Intent(this,YourService.class));
要了解有关
服务的更多信息
,您可以参考以下内容

要了解有关
asynctask
vs
service
的更多信息,您可以参考以下内容


我将与您分享我们在应用程序上所做的事情

为了保持用户会话(我们使用OAuth和访问/刷新令牌),我们在应用程序扩展类中创建了一个单例。为什么我们在MainApplication类中声明此单例?(这是我们类的名称),因为您的单例生命将被整理到创建它的活动中,因此如果您的应用程序在内存不足的情况下运行,并且垃圾收集器收集您暂停的活动,它将释放您的单例实例,因为它与该活动关联

只要用户继续使用你的应用程序,在你的应用程序类中创建它就会让它存在于你的RAM中


然后,为了保持跨应用程序会话使用的持久性,我们将凭据保存在SharedReferences中,对字段进行加密。

是同时启动2个或多个异步任务可能会在某些设备上导致问题。几个月前我就遇到过这个问题。我无法预测第二个异步任务何时无法运行。该问题是间歇性的,可能是由于在asynctask中执行ndk代码时使用了内存造成的。但我清楚地记得,这取决于设备的内存。

以前也有人问过类似的问题。我会发布类似问题的链接

一些用户建议使用
服务
。我的建议是,现在还不要走那条路。使用服务要复杂得多。即使您使用的是服务,您仍然需要处理线程,就像

请注意,与其他应用程序对象一样,服务在主应用程序中运行 他们的托管进程的线程。这意味着,如果您的服务 去做任何CPU密集型(如MP3播放)或阻塞(如 作为网络(networking)操作,它应该生成自己的线程,在其中 做那件事

如果我们能用优雅的方式解决问题,不要用复杂的方式

我建议您尝试
java.util.concurrent
中的一个API,如下所示

AsyncTask被设计成一个围绕线程和处理程序的助手类 并且不构成通用线程框架。异步任务 理想情况下,应用于短时间操作(每次几秒钟 如果需要让线程长时间运行, 强烈建议您使用 并发包,如Executor、ThreadPoolExecutor和 未来任务

到目前为止,我无法给出任何代码示例,因为我不知道您是如何设计会话管理机制的

如果您认为长时间运行的会话管理任务不应与主应用程序生命周期的生命周期相关联,那么只有您可能想考虑<代码>服务< /代码>。但是,请记住,主应用程序和

服务之间的通信要复杂得多


有关更多详细信息,请参阅“您应该使用服务还是线程?”一节中的“

就像这里的其他一些人一样,我反对这个问题的前提

您的核心问题是使用
AsyncTask
执行超出其范围的任务。其他人也注意到了这一点。那些通过低级线程(甚至
java.util.Concurrent
都是低级线程,这就是Scala使用Akka actors作为抽象的原因),
Service
等提供解决方案的人非常聪明,但他们是在治疗症状,而不是治愈疾病

至于你应该做什么,你不是第一个想要在Android应用程序中维护用户会话的人。这是一个已解决的问题。这些解决方案中的共同点(没有双关语)是使用
SharedReferences
。这是一个简单的例子。将
SharedReferences
与OAuth相结合,以实现更复杂的功能


在软件开发中,通过首先防止问题发生来解决问题是很常见的。我认为可以通过不运行synchronous
AsyncTask
s来解决运行synchronous
AsyncTask
s的问题。用户会话管理根本不是
异步任务的用途。

我在某个地方读到,如果异步任务已经在运行,我们就不能启动新的异步任务。

是的,这是一个事实,在API 11下,您不能同时运行超过5(五)
AsyncTask
,但对于更多的是,您可以使用

AsyncTask使用线程池模式运行
doInBackground()
中的内容。问题是最初(在早期的Android操作系统版本中)池大小只有1,这意味着没有pa
The task can be executed only once (an exception will be thrown if a second execution is attempted.) 
Executor executor = anExecutor;
executor.execute(new RunnableTask1());
executor.execute(new RunnableTask2());
...