我想确保我不会减慢我的应用程序的启动时间并且需要启动与用户输入无关的后台任务——例如,填充缓存。
如果我AsyncTask
从我onCreate
的方法开始,该方法何时doInBackground
真正开始执行?(假设单核设备)
Android是否有可能在onCreate/onResume
完成之前安排它,或者它是否足够聪明地认识到后台线程不应该在UI线程完全完成之前运行?
我想确保我不会减慢我的应用程序的启动时间并且需要启动与用户输入无关的后台任务——例如,填充缓存。
如果我AsyncTask
从我onCreate
的方法开始,该方法何时doInBackground
真正开始执行?(假设单核设备)
Android是否有可能在onCreate/onResume
完成之前安排它,或者它是否足够聪明地认识到后台线程不应该在UI线程完全完成之前运行?
如果您查看AsyncTask
源代码,您会发现它只是使用ThreadPoolExecutor
或串行执行器来运行任务。默认内部行为取决于 Android 版本(来自 AsyncTask 文档):
首次引入时,AsyncTask 在单个后台线程上串行执行。从 DONUT 开始,这被更改为允许多个任务并行运行的线程池。从 HONEYCOMB 开始,任务在单个线程上执行,以避免并行执行导致的常见应用程序错误。
但无论如何,doInBackground
执行与Activity
生命周期无关,因此AsyncTask
几乎可以随时执行。这仅取决于您已经启动了多少任务,默认情况下Executor
由AsyncTask
线程调度程序使用和使用。
I usually use AsyncTask
s in onCreate()
like this:
private MySuperSpecialTask mySuperSpecialTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(...);
// [...]
mySuperSpecialTask = new MySuperSpecialTask();
mySuperSpecialTask.execute();
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mySuperSpecialTask != null) {
mySuperSpecialTask.cancel(true);
}
}
This makes sure that everything is initialized before the task gets started.
实际上严格来说,您的 UI 代码没有执行顺序并启动我发现的 asynctask。通常人们不会遇到这种情况,但是,如果您的 UI 线程由于某种原因需要更长的时间,例如等待外部输入等,则 asynctask 可能在 UI 代码完成之前就已启动。
编写 UI 代码只是对 Android 系统的一个请求,它在执行循环中等待。因此,如果 asynctask 在此之前启动,因为有足够的资源(或者如上所述的 UI 线程由于任何原因而延迟),则没有执行顺序保证。
执行此操作的一种简单方法是-如果您不介意并且可以确定它足够了-使用 ScheduledExecutorService 延迟异步任务的启动,或者“更清洁”的方法是实现某种等待的看门人将标志设置为 true,然后启动 asynctask。或者你甚至可能在你的 asynctask 开始时有一个 while 循环,它等待标志设置为 true,就像在许多与外部设备的通信情况下一样。
在您可以(通常)确定您的 UI 已完成之后,该标志将设置为 true。