gpt4 book ai didi

android - 异步任务Android执行

转载 作者:IT老高 更新时间:2023-10-28 23:12:55 26 4
gpt4 key购买 nike

这是在一次 Android 采访中提出的。有人问我是否可以从异步任务 1(让它成为 Task1)的 doInBackground() 方法启动另一个异步任务(让它成为 Task2)。我浏览了文档,其中包含以下内容:

The task instance must be created on the UI thread.

execute(Params...) must be invoked on the UI thread.

根据这些陈述,我认为不可能从另一个任务的后台方法启动一个任务。此外,异步任务具有 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() 方法开始第二个任务。 我想要一些关于这里发生的事情的帮助。谢谢。

最佳答案

让我们将您的代码更改为以下内容:

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();

try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}

Log.v ("gaurav", "Log after sleeping");

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;
}
}

现在 LogCat 返回:

08-07 06:13:44.208    3073-3073/testapplication V/gaurav﹕ Thread is : main
08-07 06:13:44.209 3073-3091/testapplication V/gaurav﹕ Thread task 1 is : AsyncTask #1
08-07 06:13:49.211 3073-3091/testapplication V/gaurav﹕ Log after sleeping
08-07 06:13:49.213 3073-3095/testapplication V/gaurav﹕ Thread task 2 is : AsyncTask #2
08-07 06:13:49.213 3073-3095/testapplication V/gaurav﹕ Task 2 Started

如您所见 Task 2Task 1 结束后执行执行(即使在 sleep 5 秒后)。这意味着在第一个任务完成之前不会开始第二个任务。

为什么?背后的原因是source code of AsyncTask .请考虑 execute()方法:

public synchronized void execute(final Runnable r) {
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}

scheduleNext()方法:

protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}

这些方法中最重要的关键字是synchronized这确保了这些方法只能同时在一个线程中运行。当您调用execute方法,它提供了一个新的 RunnablemTask这是 ArrayDeque<Runnable> 的一个实例作为不同线程上不同请求的序列化器的类 [more info] .如果没有执行Runnable (即 if (mActive == null) ),scheduleNext()将被调用,否则,scheduleNext()finally block 将在当前执行的(出于任何原因)结束后调用 Runnable .全部 Runnable s 由 THREAD_POOL_EXECUTOR 在单独的线程上执行.

从其他线程执行 AsyncTask 有什么问题? 从 Jelly Bean 开始,一个 AsyncTask在 UI 线程上的应用程序启动时加载类,因此保证回调发生在 UI 线程上,但是,在 Jelly Bean 发布之前,如果另一个线程创建 AsyncTask回调可能不会发生在正确的线程上。

所以,AsyncTask只能在 Jelly Bean 之前的平台上从 UI 线程调用实现(++)。


澄清:请考虑以下示例,它只是澄清了不同平台版本的 Android 之间的差异:

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);

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

class Task1 extends AsyncTask {
@Override
protected Object doInBackground(Object... params) {
return null;
}
}

它在 Android 5.1 上运行良好,但在 Android 2.3 上崩溃并出现以下异常:

08-07 12:05:20.736      584-591/github.yaa110.testapplication E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-8
java.lang.ExceptionInInitializerError
at github.yaa110.testapplication.Main2Activity$1.run(Main2Activity.java:21)
Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:121)
at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
at android.os.AsyncTask.<clinit>(AsyncTask.java:152)
            at github.yaa110.testapplication.Main2Activity$1.run(Main2Activity.java:21)

关于android - 异步任务Android执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31874990/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com