【发布时间】:2015-08-07 10:00:44
【问题描述】:
这是在一次 Android 采访中提出的。有人问我是否可以从异步任务 1(让它成为 Task1)的 doInBackground() 方法启动另一个异步任务(让它成为 Task2)。我浏览了文档,其中包含以下内容:
任务实例必须在 UI 线程上创建。
execute(Params...) 必须在 UI 线程上调用。
根据这些陈述,我认为不可能从另一个任务的后台方法启动一个任务。此外,异步任务具有 UI 方法(不能在后台线程上使用),因此加强了我的论点,我回答为不可能。
在查看一个简单的演示应用程序时,我发现确实可以这样做。 一些演示代码:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
init();
Log.v ("gaurav", "Thread is : " + Thread.currentThread().getName());
Task1 task = new Task1();
task.execute();
}
class Task1 extends AsyncTask {
@Override
protected Object doInBackground(Object... params) {
// TODO Auto-generated method stub
Log.v ("gaurav", "Thread task 1 is : " + Thread.currentThread().getName());
Task2 task = new Task2();
task.execute();
return null;
}
}
class Task2 extends AsyncTask {
@Override
protected Object doInBackground(Object... params) {
// TODO Auto-generated method stub
Log.v ("gaurav", "Thread task 2 is : " + Thread.currentThread().getName());
Log.v ("gaurav", "Task 2 started");
return null;
}
}
我得到以下指示成功执行的日志:
> 08-07 09:46:25.564: V/gaurav(2100): Thread is : main 08-07
> 09:46:25.564: V/gaurav(2100): Thread task 1 is : AsyncTask #3 08-07
> 09:46:25.564: V/gaurav(2100): Thread task 2 is : AsyncTask #4 08-07
> 09:46:25.564: V/gaurav(2100): Task 2 started
我已经在 ICS、KK 和 L 设备上进行了检查,它适用于所有人。
我能想到的一个原因是我没有覆盖任何 UI 方法并在我的第二个任务中进行任何 UI 更新,因此它不会导致任何问题,但我不确定。即使是这样,它也违反了开发者指南中提到的线程规则。
作为参考,我也查看了此链接:Start AsyncTask from another AsyncTask doInBackground(),但答案表明使用 doInBackground() 中的 runOnUiThread() 方法启动第二个任务。 我想要一些关于这里发生的事情的帮助。谢谢。
【问题讨论】:
-
我在面试中使用类似问题的另一个原因是确定候选人是否知道从 Honeycomb 向上破坏 AsyncTasks 中的线程行为变化:stackoverflow.com/questions/21165505/…
-
@adelphus,我不太明白“从HONEYCOMB开始,任务在单线程上执行,以避免并行执行导致的常见应用程序错误”的含义。它确实定义了串行执行,但是在我的问题的上下文中,嵌套任务仍然会让它们的 onPreExecute() / onPostExecute() 在后台线程上运行?或者正如下面的答案所说的关于应用程序启动时的类加载,在这种情况下,所有嵌套任务的 onPre/onPost 方法都在 UI 线程上运行,无论任务从哪里开始?
-
这里有两个问题:我的评论是在谈论多个 AsyncTask 曾经以每个任务 1 个线程并行运行的事实。自 Honeycomb 以来,现在多个 AsyncTask 排队,因此它们都在单个线程上运行 - 一次只能运行 1 个。由于开发人员假设任务并行运行,因此更改破坏了很多代码。您关于 onPreExecute/onPostExecute 是否在 UI 线程上执行的问题是另一个问题,但 yaa110 在他的回答中很好地描述了它。