Android AsyncTask – 避免多个实例在运行

我有AsyncTask处理一些背景HTTP的东西。 AsyncTask按计划运行(报警/服务),有时用户手动执行。

我处理来自SQLite的logging,我注意到服务器上的双重post告诉我,有时计划的任务运行,同时用户手动运行,导致相同的logging从数据库中读取和处理两次。 我处理后删除logging,但仍然得到这个。

我应该如何处理? 也许组织某种排队?

Solutions Collecting From Web of "Android AsyncTask – 避免多个实例在运行"

您可以使用executeOnExecutor()Executor上执行您的AsyncTask

为确保线程以串行方式运行,请使用: SERIAL_EXECUTOR

杂项: 如何使用执行程序

如果有多个活动正在访问您的数据库,为什么不创build一种网关数据库帮助程序,并使用synchronized块来确保只有一个线程可以立即访问

或者,您可以试试看是否当前正在运行任务:

 if (katitsAsyncTask.getStatus().equals(AsyncTask.Status.FINISHED)) katitsAsyncTask.execute(); else // wait until it's done. 

初始化AsyncTask为null。 只有当它为空时才创build一个新的。 在onPostExecute中,最后将其设置为null。 在onCancelled做同样的事情,如果用户取消这一点。 这里有一些未经testing的代码来说明基本的想法。

 import android.app.Activity; import android.os.AsyncTask; import android.os.Bundle; import android.view.View; import android.widget.Button; public class FooActivity extends Activity { private class MyAsyncTask extends AsyncTask<Foo, Foo, Foo> { @Override protected void onPostExecute(Foo foo) { // do stuff mMyAsyncTask = null; } @Override protected void onCancelled() { // TODO Auto-generated method stub mMyAsyncTask = null; } @Override protected Foo doInBackground(Foo... params) { try { // dangerous stuff } catch (Exception e) { // handle. Now we know we'll hit onPostExecute() } return null; } } private MyAsyncTask mMyAsyncTask = null; @Override public void onCreate(Bundle bundle) { Button button = (Button) findViewById(R.id.b2); button.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if (mMyAsyncTask == null) { mMyAsyncTask = new MyAsyncTask(); mMyAsyncTask.execute(null); } } }); } 

}

我知道这是前一阵子,而你已经解决了你的问题。 但我也有类似的问题。 里诺的build议使我走上正轨,但对于那些一直难以填补空白的人来说。 这是我如何克服类似的问题,凯特的。

我想要一个特定的AsyncTask只运行,如果它当前不在运行。 作为Renobuild议的一个转发,AsyncTask接口已经被创build,可以处理Android中所有线程的正确处理。 这意味着,执行者是内置的。正如本博客所示:

“当在AsyncTask上调用execute(Object .. params)时,任务在后台线程中执行。根据平台的不同,AsyncTasks可以连续执行(1.6之前,可能再次4+),或者同时执行(1.6-3.2) 。

为了确保按照您的要求连续或同时运行,从API Level 11起,您可以使用executeOnExecutor(Executor executor,Object .. params)方法,并提供一个执行程序。 该平台提供了两个方便的执行程序,分别为AsyncTask.SERIAL_EXECUTOR和AsyncTask.THREAD_POOL_EXECUTOR。 “

因此,考虑到这一点,您可以通过AsyncTask接口进行线程阻塞,这也意味着您可以简单地使用AsyncTasks.getStatus()来处理线程阻塞,就像DeeV在这篇文章中所build议的那样。

在我的代码中,我pipe理这个:

创build一个全局variables定义如下:

 private static AsyncTask<String, Integer, String> mTask = null; 

在onCreate中,将其初始化为一个名为CalculateSpecAndDraw的AsyncTask实例:

 mTask = new CalculateAndDrawSpec(); 

现在,当我想调用这个AsyncTask时,我用下面的方法来包围执行:

 if(mTask.getStatus() == AsyncTask.Status.FINISHED){ // My AsyncTask is done and onPostExecute was called mTask = new CalculateAndDrawSpec().execute(Integer.toString(progress)); }else if(mTask.getStatus() == AsyncTask.Status.PENDING){ mTask.execute(Integer.toString(progress)); }else{ Toast.makeText(PlaySpecActivity.this, "Please Wait..", 1000).show(); } 

如果完成了这个新的线程,或者如果线程状态是PENDING,线程被定义但是还没有启动,我们启动它。 但是,如果线程正在运行,我们不会重新运行它,我们只是通知用户它没有完成,或者执行我们希望的任何操作。 那么如果你想安排下一个事件,而不是阻止它重新运行,请查看这个关于使用执行程序的文档。

尝试让一些实例布尔值在asynctask的预先执行上设置为“true”,然后在postexecute上设置为“false”。 然后可能在dobackbackground检查布尔值是否为true。 如果是这样,那么调用该特定重复任务的取消。

您可以保持共享首选项中的任务状态。 在开始任务之前检查值(布尔可能)。 在onPostExecute中将状态设置为完成(true?),并在onPreExecute或构造函数中将其设置为false

如果只是用一个synchronized方法包装你的check-what-to-sendsend-it逻辑呢? 这种方法似乎为我们工作。