当用户登录我的应用时。我正在开始asynctask
来维护用户会话。并且异步任务无限期地运行直到用户注销。我的问题是,当我尝试启动其他asynctasks
时,他们的doInBackground()
方法永远不会被执行。
我在某处读到,如果异步任务已在运行,我们就无法启动新的async task
。我可以确认这一点,因为当我删除用户会话异步任务时,它正常工作。有解决方法吗?
P.S。:我已经使用过executeOnExecutor()
方法。但它没有帮助。
答案 0 :(得分:6)
对于可能长时间运行的操作,我建议您使用Service
而不是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));
要了解有关Service
的更多信息,请参阅此
要了解有关asynctask
vs service
的更多信息,请参阅此
答案 1 :(得分:4)
我在某处读到,如果异步任务已在运行,我们就无法启动新的异步任务。
是的,事实上,您无法在API 11下同时运行超过5(5)
AsyncTask
但是更多是,您可以使用executeOnExecutor。AsyncTask使用线程池模式来运行
doInBackground()
中的内容。问题最初(在早期的Android OS版本中)池大小只有1,这意味着没有对一堆AsyncTasks进行并行计算。但后来他们修复了这个问题,现在大小为5,所以最多可以同时运行5个AsyncTasks。
我弄明白 Some Threading rules,我发现下面有一条主要规则,
The task can be executed only once (an exception will be thrown if a second execution is attempted.)
AsyncTask
的定义是什么?
AsyncTask可以正确,轻松地使用UI线程。该类允许执行后台操作并在UI线程上发布结果,而无需操纵线程和/或处理程序。
如何&在哪里使用?
AsyncTask旨在成为Thread和Handler的辅助类,并不构成通用的线程框架。理想情况下,AsyncTasks应该用于短操作(最多几秒钟)。如果需要保持线程长时间运行,强烈建议使用它。
为什么您不能同时使用多个AsyncTask
?
此类必须遵循一些线程规则才能正常工作:
execute(Params...)
。onPreExecute(), onPostExecute(Result), doInBackground(Params...), onProgressUpdate(Progress...)
。该任务只能执行一次(如果尝试第二次执行,则会抛出异常。)
Running multiple AsyncTasks at the same time — not possible?
尝试使用执行程序
你应该使用Executor来管理你的多线程并行。
Executor executor = anExecutor;
executor.execute(new RunnableTask1());
executor.execute(new RunnableTask2());
...
答案 2 :(得分:3)
就像其他几个人一样,我反对这个问题的前提。
您的核心问题是您使用AsyncTask
执行超出其范围的任务。其他人也注意到了这一点。那些提供可以通过低级线程(甚至java.util.Concurrent
来缓解问题的解决方案的人是低级的,这就是为什么Scala使用Akka actor作为抽象),Service
,等。他们非常聪明,但他们正在治疗这种症状,而不是治愈这种疾病。
至于你应该做什么,你不是第一个想要在Android应用程序中维护用户会话的人。这是一个已解决的问题。这些解决方案中的共同主题(没有双关语)是SharedPreferences
的使用。 Here是一个直截了当的例子。 This Stack Overflow user将SharedPreferences
与OAuth结合起来,做更复杂的事情。
在软件开发中通常首先防止问题的发生来解决问题。我认为你可以通过不同时运行AsyncTask
来解决同时运行AsyncTask
的问题。用户会话管理根本不是AsyncTask
的用途。
答案 3 :(得分:2)
如果您正在为API 11或更高版本进行开发,则可以使用AsyncTask.executeOnExecutor()
允许一次运行多个AsyncTasks。
答案 4 :(得分:2)
我将与您分享我们在应用上的所作所为。
要保留用户会话(我们将OAuth与访问/刷新令牌一起使用),我们会在应用程序扩展类中创建 Singleton 。为什么我们在MainApplication类中声明这个Singleton? (这就是我们班级的名字),因为你的 Singleton的生活将被创造出创建它的活动,所以如果你的应用程序在低内存上运行而垃圾收集器收集你暂停的活动,它将会释放您的Singleton实例,因为它与该Activity关联。
只要用户继续使用您的应用程序,在Application类中创建它就会让它存在于RAM中。
然后,为了保持跨应用程序使用的会话,我们将凭据保存在加密字段的SharedPreferences中。
答案 5 :(得分:1)
是同时启动2个或更多asynctasks可能会导致某些设备出现问题。几个月前我曾经历过这个问题。我无法预测第二个asyncTask何时无法运行。问题是由于我在asynctask中执行ndk代码而导致内存使用造成的间歇性问题。但我记得很清楚它取决于设备的记忆。
答案 6 :(得分:1)
之前曾有人问过类似的问题。我会发布类似问题的链接。
AsyncTask.executeOnExecutor() before API Level 11
有些用户建议使用Service
。我的建议是不要去那条路。使用服务要复杂得多。即使您正在使用服务,您仍然必须处理线程,如
请注意,服务与其他应用程序对象一样,在main中运行 他们的托管过程的线程。这意味着,如果您的服务是 要做任何CPU密集型(如MP3播放)或阻塞(如此 作为网络)操作,它应该在其中产生自己的线程 做那件事....
如果我们能够以优雅的方式解决问题,请不要采用复杂的方式。
我建议您尝试java.util.concurrent
中的一个API,如下所示
AsyncTask旨在成为Thread和Handler的辅助类 并不构成通用的线程框架。 AsyncTasks 理想情况下应该用于短期操作(几秒钟的时间) 大多数。)如果你需要保持线程长时间运行, 强烈建议您使用提供的各种API java.util.concurrent pacakge如Executor,ThreadPoolExecutor和 FutureTask。
到目前为止,我无法向您提供任何代码示例,因为我不知道您如何设计会话管理机制。
如果您认为长时间运行的会话管理任务不应该绑定到主应用程序生命周期的生命周期,那么只有您可能需要考虑Service
。但是,请记住,主应用程序和Service
之间的通信更加繁琐复杂。
有关详细信息,请参阅http://developer.android.com/guide/components/services.html部分您是否应该使用服务或主题?