【问题标题】:AsyncTask doInBackground does not run [duplicate]AsyncTask doInBackground 不运行 [重复]
【发布时间】:2011-05-04 02:35:29
【问题描述】:

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

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

ImageActivity 非常简单。它有一个设置布局的 onCreate,然后它启动一个新的 AsyncTask 从互联网加载图像。这在前几次工作正常。但它突然停止工作。每次都会运行 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);
    }
}

更新:

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

【问题讨论】:

  • 发布您的代码。你怎么称呼它。我们不知道如何在没有代码的情况下为您提供帮助
  • 有完全相同的问题,在我的应用程序中启动多个 AsyncTasks 后,应用程序只执行到 onPreExecute(),但没有进入 doInBackground()。现在尝试你的线程方法..
  • 我也有同样的问题。奇怪的是,它因设备而异。它发生在平板电脑(Android 4.0)上,但运行完全相同代码的手机(Android 2.3.4)没有。
  • 在我的情况下 doInBackground 有效,但里面的 Log.d() 无效!

标签: android android-asynctask


【解决方案1】:

删除 AsyncTask 并使用 traditional Thread 而不是将其与 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();
    }
}

【讨论】:

  • 谢谢,我也有同样的问题(不久前在 SO 上发布过,但没有解决问题)谷歌搜索把我带到了这里 :)
  • 这揭示了为什么 AsyncTask 可能让你(和我!)失败:foo.jasonhudgins.com/2010/05/limitations-of-asynctask.html
  • 只是分享一个想法,我最近遇到了类似AsyncTask 的巫毒教行为。但是,我在后台关闭了一个已经在运行的AsyncTask 后通过了它。很奇怪,但它对我有用。
  • 我的回答概述了失败的具体原因。 stackoverflow.com/a/20620623/9636
【解决方案2】:

我遇到了类似的问题。在 SDK 11 之前,您不能让多个 Asynctask 并行运行。检查here for more info

【讨论】:

    【解决方案3】:

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

    在首次引入时,AsyncTask 是在单个 后台线程。从 DONUT 开始,这变成了一个池 允许多个任务并行运行的线程。从...开始 HONEYCOMB,任务在单线程上执行,避免常见 并行执行导致的应用程序错误。

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

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

    【讨论】:

    • doInBackground() 不应该让我调用 UI 方法(例如,如您提到的那样弹出对话框)。
    • 我在主线程上显示了对话框,但它是由doInBackground触发的。
    • 这是应该被接受的正确答案。 (刚刚完成了我自己对该主题的调查并得出了相同的结论 - 单独的执行者)
    • 所以如果我没看错这个文档,他们会从串行执行到并行执行再回到串行执行吗?现在如果我们需要同时执行两个或更多的 AsyncTask,我们需要使用多个执行器,每个执行器都运行在自己的线程上?
    • 是的,或者使用单个并行执行器。
    【解决方案4】:

    使用 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);
    
            }
      }
    

    【讨论】:

      【解决方案5】:

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

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

      【讨论】:

      • downloadBitmap 方法有点长,不是问题。如果我尝试 Thread.sleep(5000) 模拟慢速下载,我会遇到同样的问题。当我使用 Thread.sleep 时,我可以启动 ImageActivity 3-4 次并且任务有效。之后,该任务仅打印 onPreExecute 而不是“doInBackground”日志消息,这意味着由于某种原因它永远不会被调用。是的,我试图不取消任务,但我没有提供帮助。
      • 还有更多代码被你省略了吗?
      【解决方案6】:

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

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

      【讨论】:

        【解决方案7】:

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

        【讨论】:

          猜你喜欢
          • 2013-05-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-02-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多