【问题标题】:Does onPreExecute() and onPostExecute() execute on the UI thread or on the thread from which the AsyncTask has been started?onPreExecute() 和 onPostExecute() 是在 UI 线程还是在启动 AsyncTask 的线程上执行?
【发布时间】:2016-12-30 07:36:29
【问题描述】:

我一直在写AsyncTask's for short background operations in android 很长一段时间,并且有一个非常基本的问题。如果我从单独的线程而不是主 UI 线程启动 AsyncTask,我的 onPreExecute()andonPostExecute 方法是否仍会在 UI 线程或我启动 AsyncTask 的线程中调用。我很好奇,因为当我从其他线程启动它时,我无法在 onPreExecute() 方法中显示一个弹出窗口。

编辑 2

I tried writing this simple activity to try:

    public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        new Thread(new Runnable() {
            @Override
            public void run() {
                final TestAsyncTask task = new TestAsyncTask();
                task.execute();
            }
        }).start();
    }

    private class TestAsyncTask extends AsyncTask<Void, Void, Void> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected Void doInBackground(Void... voids) {
            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            Toast.makeText(MainActivity.this, "Yo!", Toast.LENGTH_LONG).show();
        }
    }
}

这运行良好。 但是当我使用以下代码运行应用程序时:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        new Thread(new Runnable() {
            @Override
            public void run() {
                final TestAsyncTask task = new TestAsyncTask();
                task.execute();
            }
        }).start();
    }

    private class TestAsyncTask extends AsyncTask<Void, Void, Void> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            Toast.makeText(MainActivity.this, "Yo!", Toast.LENGTH_LONG).show();
        }

        @Override
        protected Void doInBackground(Void... voids) {
            return null;
        }
    }
}

它失败并出现以下错误:

Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

作为堆栈跟踪中的行之一。

【问题讨论】:

  • 在Activity或Class中调用AssynTask?

标签: java android multithreading android-asynctask ui-thread


【解决方案1】:

虽然文档说这些回调在主线程中执行 - 但事实并非如此。 onPreExecute()executeOnExecutor() 同步运行,即在启动 AsyncTask 的线程中。

onPostExecute() 总是在主线程中运行。 (它是从finish() 调用的,这发生在使用主线程的looper 的Handler 内部)。

【讨论】:

  • 我尝试从 onPreExecute() 和 onPostExecute() 中创建 Toastmessage(我编辑了问题以包含代码)。在这两种情况下都失败了。
  • @Swapnil 实际上,您的代码从doInBackground() 抛出吐司。你确定来自onPostExecute() 的吐司会导致应用崩溃吗?
  • 任何人都知道如何与 Android 团队沟通,以便我们也可以在文档中包含此内容?
【解决方案2】:

您应该在运行在 UI 线程上的 AsyncTask 的 onPostExecute() 方法中进行 UI 更新和警报或弹出显示。 AsyncTask 的 doinBackground() 方法在另一个线程上运行。

【讨论】:

    【解决方案3】:

    引用官方文档:

    onPostExecute
    Added in API level 3
    void onPostExecute (Result result)
    Runs on the UI thread after doInBackground(Params...). The specified result is the value returned by doInBackground(Params...).
    
    
    onPreExecute
    Added in API level 3
    void onPreExecute ()
    Runs on the UI thread before doInBackground(Params...).
    

    你可以在这里找到它https://developer.android.com/reference/android/os/AsyncTask.html#onPostExecute(Result)

    Do in background 在后台线程上运行,而 OnPreExecute 和 OnPostExecute 在主 Ui 线程上运行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-15
      • 2019-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多