【问题标题】:AsyncTask will always run even if app is destroyed?即使应用程序被销毁,AsyncTask 也将始终运行?
【发布时间】:2013-04-25 00:54:58
【问题描述】:

我有一个应用程序,因为你不能在我使用 AsyncTask 的主线程上进行网络操作,所以问题是一旦我 execute() AsyncTask 之后我 finish()活动,也许用户会finish()整个应用程序,所以我想知道的是:

  1. 只要在应用运行时调用execute()doInBackground()onPostExecute() 是否会始终完成doInBackground()onPostExecute()

【问题讨论】:

  • 您应该使用您的活动生命周期来取消正在运行的任务,使用 Asynctask 的cancel 方法。继续网络操作是没有用的,即使您的 UI 被破坏,它也很可能继续运行。但是在网络操作完成后,它会尝试更新您的 UI 应用程序时会遇到问题。

标签: android android-asynctask android-lifecycle


【解决方案1】:

您将能够对此进行测试。是的,确实如此。如果调用了 execute,您可以看到 Asynctask 仍将执行,除非它对前台或 UI 相关的操作。 (可能会导致启动器崩溃)。


但是,如果它靠近系统。它可能会或可能不会继续执行该方法。我已经测试并回答了here。 回复评论: 已测试:

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        new Worker().execute();
    }
private class Worker extends AsyncTask<Void, Void, String> {

    @Override
    protected String doInBackground(Void... arg0) {
        Log.i("SomeTag",
                "start do in background at " + System.currentTimeMillis());
        String data = null;

        try {
            DefaultHttpClient httpClient = new DefaultHttpClient();
            HttpGet httpGet = new HttpGet(
                    "https://stackoverflow.com/questions/tagged/android");

            HttpResponse httpResponse = httpClient.execute(httpGet);
            HttpEntity httpEntity = httpResponse.getEntity();
            data = EntityUtils.toString(httpEntity);
            Log.i("SomeTag",
                    "doInBackGround done at " + System.currentTimeMillis());
        } catch (Exception e) {
        }
        return data;
    }

    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        Log.i("SomeTag", System.currentTimeMillis() / 1000L
                + " post execute \n" + result);
    }
}

@Override
protected void onDestroy() {
    super.onDestroy();
    Log.i("SomeTag", System.currentTimeMillis() / 1000L + "  onDestory()");
}

04-24 21:42:57.981: I/SomeTag(5961): start do in background at 1366854177994
04-24 21:43:00.974: I/SomeTag(5961): 1366854180  onDestory()
04-24 21:43:02.946: I/SomeTag(5961): doInBackGround done at 1366854182946
04-24 21:43:02.946: I/SomeTag(5961): 1366854182 post execute 
04-24 21:43:02.946: I/SomeTag(5961): <!DOCTYPE html>
04-24 21:43:02.946: I/SomeTag(5961): <html>
04-24 21:43:02.946: I/SomeTag(5961): <head>
04-24 21:43:02.946: I/SomeTag(5961):         
04-24 21:43:02.946: I/SomeTag(5961):     <title>Newest &#39;android&#39; Questions - Stack Overflow</title>
04-24 21:43:02.946: I/SomeTag(5961):     <link rel="shortcut icon" href="http://cdn.sstatic.net/stackoverflow/img/favicon.ico">
//....

【讨论】:

  • 谢谢这正是我想知道的,从你所说的我必须去做一些改变,试图在你知道的第一时间把它做好,谢谢你的时间
  • 我不得不在这里有点不同意。 AsyncTasks 假设与 UI 相关。 onPostExecute()总是从 UI 线程运行,因此在这种情况下永远不会调用它。
  • @Pescis 已更新并经过测试。如果您发现我的测试不准确,请指出我的错误。
  • 显然 UI 线程在 onDestroy() 之后仍然可以运行 - 没想到会这样。因此,取消任何 UI 任务以释放资源可能是一个非常好的主意。
【解决方案2】:

onPostExecute() 从 UI 线程调用 - 因此如果 UI 线程不再运行,它将不会继续运行。但是doInBackGround() 是从一个单独的工作线程运行的,因此它将一直运行到完成(或者如果 JVM 进程被操作系统杀死,这也是一种可能性)。请注意,仅建议将 AsyncTasks 用于较短的 UI 绑定后台任务,而不是长时间运行的后台工作(几秒钟)。

简而言之,你不能假设它会继续下去,也绝对不能假设它会发布进度或致电onPostExecute()

【讨论】:

    【解决方案3】:

    当你在 Activity 上调用 finish() 时,Activity 会被销毁,但主线程不会。 [注意:活动在主线程上运行。活动不是主线程。 ]

    因此,后台线程上的 doInBackground() 和主线程上的 onPostExecute() 将被执行。但是,如果 onPostExecute() 执行任何与 UI 相关的任务,您将获得 ANR,因为此时没有 UI。 例如,如果您只是在 onPostExecute() 中打印 Log.d() 语句,则该语句将在 Logcat 中可见。

    ** 只有当进程处于活动状态且未被 Android Low Memory Killer 杀死时,这些才是可能的。

    【讨论】:

      【解决方案4】:

      看图看看哪个线程执行了哪些方法。

      【讨论】:

        【解决方案5】:

        您可以轻松地对此进行测试,只需让doInBackground() 持续更长时间,例如添加Thread.sleep(5000),然后尝试各种场景:

        • 如果您完成启动 AsyncTask 的 Activity,或者离开它,AsyncTask 会正常完成,但是如果您持有对周围 Activity 的引用,您可能会导致内存泄漏或在 onPostExecute() 中崩溃您的应用程序(就像一个 UI 元素),它不再“活着”了。
        • 如果您通过按“主页”按钮最小化您的应用程序,它将再次正常完成,但可能会使应用程序崩溃onPostExecute()
        • 如果你杀死你的应用程序进程(或系统这样做),它将终止你的 AsyncTask 并且你希望它做的工作doInBackground() 将不会完成。如果您只是使用new Thread(new Runnable() {... 启动线程,情况也是如此

        【讨论】:

          猜你喜欢
          • 2023-03-02
          • 1970-01-01
          • 2011-02-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-04-15
          • 1970-01-01
          相关资源
          最近更新 更多