onPreExecute() 和 onPostExecute() 是在 UI 线程还是在启动 AsyncTask 的线程上执行?
Posted
技术标签:
【中文标题】onPreExecute() 和 onPostExecute() 是在 UI 线程还是在启动 AsyncTask 的线程上执行?【英文标题】:Does onPreExecute() and onPostExecute() execute on the UI thread or on the thread from which the AsyncTask has been started? 【发布时间】: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? 【参考方案1】:虽然文档说这些回调在主线程中执行 - 但事实并非如此。 onPreExecute()
从 executeOnExecutor()
同步运行,即在启动 AsyncTask
的线程中。
onPostExecute()
总是在主线程中运行。 (它是从finish()
调用的,这发生在使用主线程的looper 的Handler
内部)。
【讨论】:
我尝试从 onPreExecute() 和onPostExecute()
中创建 Toast
message(我编辑了问题以包含代码)。在这两种情况下都失败了。
@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 线程上运行。
【讨论】:
以上是关于onPreExecute() 和 onPostExecute() 是在 UI 线程还是在启动 AsyncTask 的线程上执行?的主要内容,如果未能解决你的问题,请参考以下文章
Android onPreExecute()、progressDialog 和 json.toString() 错误
如何从 onPreExecute() 方法中取消 ProcessDialog
Android:如何将参数传递给AsyncTask的onPreExecute()?
Android:如何将参数传递给 AsyncTask 的 onPreExecute()?
从片段调用 Android AsyncTask 没有调用其成员 - doInbackground、onpreexecute、onpostexecute