6.AsyncTask
原理
- AsyncTask的特点是任务在主线程之外运行,而回调方法是在主线程中执行,AsyncTask其实使用handler来实现异步任务的,它是一个抽象类,AsyncTask的execute在主线程中首先调用了onPreExecute做预备工作,在子线程中调用了doInBackground方法去做耗时操作,返回的数据通过Message.obtain(handler, ON_POST_MSG, result).sendToTarget()发送在主线程里
- handle的handleMessage方法调用了onPostExecute,更新ui
- AsyncTask定义了三种泛型类型 Params,Progress和Result。 Params 启动任务执行的输入参数,比如HTTP请求的URL。 Progress 后台任务执行的百分比。 Result 后台执行任务最终返回的结果,比如String。 子类必须实现抽象方法doInBackground(Params… p) ,在此方法中实现任务的执行工作,比如连接网络获取数据等。通常还应 该实现onPostExecute(Result r)方法,因为应用程序关心的结果在此方法中返回。需要注意的是AsyncTask一定要在主线程中创 建实例。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47public abstract class MyAsynTask {
protected static final int ON_POST_MSG = 0;
private MyHandler handler;
// 运行在主线程中,做准备工作
protected abstract void onPreExecute();
// 运行在子线程中,做耗时操作
protected abstract String doInBackground(String s);
// 运行在主线程中,耗时操作完成,更新ui
protected abstract void onPostExecute(String s);
public MyAsynTask() {
handler = new MyHandler();
}
public void execute(final String... strs) {
onPreExecute();
new Thread(new Runnable() {
@Override
public void run() {
String result = doInBackground(strs[0]);
Message.obtain(handler, ON_POST_MSG, result).sendToTarget();
}
}).start();
}
class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case ON_POST_MSG:
String result = (String) msg.obj;
onPostExecute(result);
break;
default:
break;
}
super.handleMessage(msg);
}
}
}
MainActivity
1 | |
AsyncTask的优缺点
使用的优点:简单、快捷、过程可控
使用的缺点:
- AsyncTask的缺陷:可以分为两个部分说,在3.0以前,最大支持128个线程的并发,每次开启10个,5个同时运行,当开第129就会奔溃。在3.0以后,无论有多少任务,都会在其内部单线程执行。在执行多个异步操作时,一个运行其他的就得等待,需要自己开启线程池,比较麻烦,
- 每次当一个任务执行完毕后,下一个任务才会得到执行,SerialExecutor模仿的是单一线程池的效果,如果我们快速地启动了很多任务,同一时刻只会有一个线程正在执行,其余的均处于等待状态。
- 在使用多个异步操作和并需要进行Ui变更时,就变得复杂起来.
- AsynTask为什么要设计为只能够一次任务?最核心的还是线程安全问题,多个子线程同时运行,会产生状态不一致的问题。所以要务必保证只能够执行一次
新版不对
1 | |
Handler的优缺点
使用的优点:
结构清晰,功能定义明确
对于多个后台任务时,简单,清晰
使用的缺点:
在单个后台异步处理时,显得代码过多,结构过于复杂(相对性)
内存泄露
SerialExecutor模仿的是单一线程池的效果,如果我们快速地启动了很多任务,同一时刻只会有一个线程正在执行,其余的均处于等待状态。
那么假设一下,如果用户开启某个页面,而此页面有Task在执行,再打开另外一个页面,这个页面还有Task需要执行,这个时候很可能会出现卡一个的情况,不是硬件配置差,而是软件质量差导致的~那么如何修复呢?
解决: cancel + isCancelled ,强烈推荐
真正决定任务取消的是需要手动调用isCancelled方法check task状态,因此推荐的修复方案是在手动调用cancel方法的同时,能调用inCancelled方法检测task状态:
1 | |
2:建议在修复方案1的基础上将AsyncTask作为静态内部类存在(与Handler处理方式相似),避免内部类的this$0持有外部类的引用
但不推荐只修改AsyncTask为静态内部类的方案,虽然不是泄露了,但没有根本上解决问题~
3:如果AsyncTask中需要使用Context,建议使用weakreference
4:如果确实需要做相对耗时的操作,建议用service去做,而不要用AsyncTask,推荐
6.AsyncTask
http://peiniwan.github.io/2025/12/e01ee5fe9518.html