在Android中,所有耗时操作都不能放在主线程(即UI线程)中执行,否则会引起ANR异常,进而导致应用程序崩溃。解决办法是使用多线程,将耗时操作放到异步子线程中执行。
Android中实现多线程有两种基本方法:
1. Thread + Handler
2. AsyncTask
其中AsyncTask可以视为是对Thread + Handler机制的再次封装实现。一般来说,数据简单、耗时较短的单个后台异步处理使用AsyncTask,此方法实现代码较为简单,而且更新UI控件更为简单;而执行时间长且逻辑复杂的多后台任务则使用Thread + Handler,此方法与AsyncTask相比能更好的利用系统资源,但是和UI线程的通信会更为复杂。
Android系统推荐使用AsyncTask来处理简单的异步操作,通常是在Activity中通过内部类的方式来使用AsyncTask,若不使用内部类,则无法直接更新UI控件,这就失去了使用AsyncTask的意义,不如直接使用Thread + Handler机制来实现多线程。
在Android中,线程池是有限的,创建过多的异步线程会导致ANR异常,除此之外,使用AsyncTask还需要注意以下这些问题:
- 由于 AsyncTask 内部的线程池是 static 类型,整个进程共用一个线程池;如果使用不当,会产生阻塞问题,尤其是单任务顺序执行的情况下,一个任务执行时间过长会阻塞其他任务的执行
- static 线程另外一个问题是,如果第一次调用 AsyncTask 在非 UI 线程中,那么以后使用 AsyncTask时,onPosExecute 也会在非 UI 线程中,此时如果执行 UI 操作会 Crash,所以第一次使用 AsyncTask 一定要在 UI 线程中使用,尤其是使用第三方 SDK 时要注意这点
- 通常使用 AsyncTask 是在 Activity 中使用匿名的内部类来使用,内部类的一个问题是会保持外部类的实例,如果 AsyncTask 中的异步任务在 Activity 退出时还没执行完或者阻塞了,那么这个保持的外部的 Activity 实例得不到释放,会引起 OOM 问题,解决办法是:在 AsyncTask 使用弱引用外部实例,或者保证在 Activity 退出时,所有的 AsyncTask 已执行完成或被取消
关于AsyncTask导致的内存泄漏问题,可参考下面这篇文章: