AsyncTask doInBackground不运行

时间:2010-11-02 18:17:48

标签: android android-asynctask

我遇到了AsyncTask类的问题。在创建4个或5个任务后,我的任务似乎停止了。

我有2项活动。 MainActivity只包含一个按钮,用于启动名为ImageActivity的第二个活动。

ImageActivity非常简单。它有一个onCreate设置布局,然后它启动一个新的AsyncTask,从Internet加载图像。这在前几次工作正常。但它突然停止工作。每次运行onPreExecute方法,但不运行doInBackground方法。我试图用睡眠循环简化doInBackground,同样的事情发生了。我无法理解这种行为,因为asynctask在onDestroy方法中都被取消并设置为null。所以每次我开始一个新的ImageActivity时,我也会创建一个新的AsyncTask。

我通过点击后退按钮重新创建ImageActivity和任务,而不是单击MainActivity上的按钮。

任何想法?我真的很挣这个。

更新:启动ImageActivity的代码(在onClickListener按钮内)

Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
intent.setClassName(this, ImageActivity.class.getName());
startActivity(intent);

上面的代码启动了此活动

    public class ImageActivity extends Activity {

    private AsyncTask<Void, Void, Void> task;

    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.main);

        task = new AsyncTask<Void, Void, Void>() {

            @Override
            protected void onPreExecute()
            {
                Log.d(TAG, "onPreExecute()");
            }

            @Override
            protected Void doInBackground(Void... params)
            {
                Log.d(TAG, "doInBackground() -- Here is the download");
                // downloadBitmap("http://mydomain.com/image.jpg")
                return null;
            }

            @Override
            protected void onPostExecute(Void res)
            {
                Log.d(TAG, "onPostExecute()");
                if(isCancelled()){
                    return;
                }
            }
        }.execute();
    }

    @Override
    protected void onDestroy()
    {
        super.onDestroy();
        task.cancel(true);
    }
}

更新:

我已经使用传统Threads和runOnUiThread方法的组合进行了测试,似乎效果更好。现在线程每次运行。

7 个答案:

答案 0 :(得分:23)

删除AsyncTask并使用传统线程而不是将其与 runOnUiThread 结合使用似乎可行。但我仍然没有找到AsyncTask如此“不稳定”的原因。

以下是适用于我的代码:

public class ImageActivity extends Activity {

    private Thread worker;

    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.main);

        worker = new Thread(new Runnable(){

            private void updateUI(final List<Object> list)
            {
                if(worker.isInterrupted()){
                    return;
                }
                runOnUiThread(new Runnable(){

                    @Override
                    public void run()
                    {
                        // Update view and remove loading spinner etc...
                    }
                });
            }

            private List<Object> download()
            {
                // Simulate download
                SystemClock.sleep(1000);
                return new ArrayList<Object>();
            }

            @Override
            public void run()
            {
                Log.d(TAG, "Thread run()");
                updateUI(download());
            }

        });
        worker.start(); }

    @Override
    protected void onDestroy()
    {
        super.onDestroy();
        worker.interrupt();
    }
}

答案 1 :(得分:7)

我遇到了类似的问题。在SDK 11之前,您无法并行运行多个Asynctasks。请检查here for more info

答案 2 :(得分:6)

我也遇到了这个问题。如果您使用AsyncTask.execute,则您的任务将在串行队列上运行(来自Android 4.3源代码):

  

首次引入时,AsyncTasks在单个上串行执行   背景线程。从DONUT开始,这被改成了一个池   允许多个任务并行运行的线程。从...开始   HONEYCOMB,任务在单个线程上执行以避免常见   并行执行导致的应用程序错误。

这与我所看到的行为一致。我在AsyncTask中弹出了一个doInBackground对话框并阻止对话框关闭。该对话框需要自己的AsyncTask才能完成。对话框的AsyncTask.doInBackground方法从未执行过,因为原来的AsyncTask仍然被阻止。

解决方案是在单独的AsyncTask中执行第二个Executor

答案 3 :(得分:1)

使用traceview调查 - 或获取线程转储。我的猜测是你的一个AsyncTask线程正在下载。

AsyncTask有一个小的线程池,所以如果你的一个任务挂起,它最终可能会阻塞你的线程池。

这是一个你可以运行的快速测试 - 在4.3,我看到我只能运行5个并发线程。当一个线程退出时,其他线程启动。

  private void testAsyncTasks() {

        for (int i = 1; i <= 10; i++) {
              final int tid = i;
              new AsyncTask<Integer, Void, Void>() {
                    protected void onPreExecute() {
                          Log.d("ASYNCTASK", "Pre execute for task : " + tid);
                    };

                    @Override
                    protected Void doInBackground(Integer... args) {
                          int taskid = args[0];
                          long started = SystemClock.elapsedRealtime();
                          Log.d("ASYNCTASK", "Executing task: " + taskid + " at " + started);
                          for (int j = 1; j <= 20; j++) {
                                Log.d("ASYNCTASK", "   task " + taskid + ", time=" + (SystemClock.elapsedRealtime() - started));
                                SystemClock.sleep(1000);
                          }
                          return null;
                    }

                    protected void onPostExecute(Void result) {
                          Log.d("ASYNCTASK", "Post execute for task : " + tid);
                    };
              }.execute(i);

        }
  }

答案 4 :(得分:0)

您不必担心Android中的内务处理线程,因为它由系统管理。

请同时发布图片下载方法。您是否还尝试过取消onDestroy()方法中的线程?你是如何将图像返回到UI线程的?

答案 5 :(得分:0)

我认为问题在于繁重的图像下载任务。即使取消异步任务,图像下载也将继续执行,并且在下载完成之前,异步任务不会完成。您可能希望在下载过程中检查AyncTask上的isCancelled()方法,并在任务被取消时终止下载。

供参考,下面是关于cancel()方法的文档: 尝试取消执行此任务。如果任务已经完成,已经取消或由于某些其他原因无法取消,则此尝试将失败。如果成功,并且在调用cancel时此任务尚未启动,则此任务永远不会运行。如果任务已经启动,则mayInterruptIfRunning参数确定执行此任务的线程是否应该在尝试停止任务时被中断。 调用此方法将导致在doInBackground(Object [])返回后在UI线程上调用onCancelled(Object)。调用此方法可确保永远不会调用onPostExecute(Object)。在调用此方法之后,您应该定期从doInBackground(Object [])检查isCancelled()返回的值,以尽早完成任务。

答案 6 :(得分:0)

我也有这个,没有真正的理由不开始。我注意到重新启动adb后它又恢复了工作。不知道为什么会这样,但它对我有用