线程作为CPU最小调度单位,使我们开发中进程需要用到的功能。在Android中,除了java原本就提供的Thread以外,还提供了其他形式的线程,如AsyncTask、IntentService、HandlerThread, 它们的底层还是都封装的Thread,但却提供了更加丰富的功能。所以在Android中,常用的线程的形态有:
- 1、Thread;
- 2、AsyncTask;
- 3、IntentService;
- 4、HandlerThread;
1、AsyncTask
AsyncTask的底层其实用到了线程池,它并不适合进行特别耗时的后台任务,如果有耗时较长的任务,建议使用线程池。原因就在于AsyncTask的任务默认是串行执行的,如果前面的任务很耗时,则后面的任务长期都得不到执行。AsyncTask的源码分析将放到下一篇博客中来进行,本篇先讲它的使用。
核心方法:
- excute: 创建好AsyncTask对象后,需要调用此方法才开始执行任务;
- onPreExecute:在主线程中执行,在异步任务执行之前执行,可以做一些准备工作;
- doInBackground:在线程池中执行,执行具体的异步任务。在这个方法中可以调用publishProgress方法来更新任务的进度;
- onProgressUpdate:在主线程中执行,调用publishProgress方法后会被调用;
- onPostExecute:在主线程中执行,异步任务执行完毕后会被调用,返回执行结果;
- onCancelled:在主线程中执行,异步任务被取消时会被调用,这样onPostExecute方法将不会被调用;
以上方法中,只有doInBackground方法是在线程池中去执行的,毕竟耗时操作也是在这个方法中去完成的。
示例代码如下:
private class MyTask extends AsyncTask<Params, Progress, Result> {
....
// 作用:执行 线程任务前的操作
@Override
protected void onPreExecute() {
...
}
// 作用:接收输入参数、执行任务中的耗时操作、返回 线程任务执行的结果
@Override
protected String doInBackground(String... params) {
...
// 可调用publishProgress()显示进度, 之后将执行onProgressUpdate()
publishProgress(count);
}
// 作用:在主线程 显示线程任务执行的进度
@Override
protected void onProgressUpdate(Integer... progresses) {
...
}
// 作用:接收线程任务执行结果、将执行结果显示到UI组件
@Override
protected void onPostExecute(String result) {
...// UI操作
}
// 作用:将异步任务设置为:取消状态
@Override
protected void onCancelled() {
...
}
}
MyTask mTask = new MyTask();
mTask.execute();
使用AsyncTask有几个点需要特别注意:
- 1、AsyncTask的类必须在主线程中被加载,即第一次访问AsyncTask这个类必须在主线程中进行,这一点在Android4.1及以上版本,已由系统本身完成,在ActivityThread的main方法调用了AsyncTask的init方法,从而完成了类加载;
- 2、AsyncTask对象必须在主线程中创建;
- 3、execute方法必须在主线程中调用;
- 4、以上方法除了execute和onCancelled方法,其他方法不要在代码中主动去调用,这个Android内部已经封装好了,有一套完整的调用机制,我们只需要重写这几个方法即可;
- 5、一个AsyncTask对象只能调用一次execute方法。否则会报错;
2、HandlerThread
HandlerThread继承自Thread,它的实现很简单,就是在内部封装了Handler以及创建了对应的Looper对象,从而可以像主线程一样使用Handler消息机制来处理多个任务,它的源码如下:
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;
//构造方法需要传入线程的名字
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
//用来重写,在开启消息循环之前被调用
protected void onLooperPrepared() {
}
//主要的地方在这个run方法
@Override
public void run() {
mTid = Process.myTid();
//创建消息队列
Looper.prepare();//在run方法的开始,创建Looper对象和MessageQueue
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
//开启消息循环
Looper.loop();//在run方法的末尾,开启消息循环
mTid = -1;
}
public Looper getLooper() {
if (!isAlive()) {
return null;
}
// If the thread has been started, wait until the looper has been created.
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
//用于停止消息循环
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
//用于停止消息循环
public boolean quitSafely() {
Looper looper = getLooper();
if (looper != null) {
looper.quitSafely();
return true;
}
return false;
}
public int getThreadId() {
return mTid;
}
}
所以,如果我们要想在一个子线程中简单的去使用Handler消息机制,直接使用此类即可,就不需要自己另行封装了。HandlerThread在源码中的一个使用场景就是IntentService,下面将讲到。
3、IntentService
- IntentService 是一个抽象类,所以必须创建它的子类才能使用IntentService
- IntentService继承自Service,因此是一种特殊的服务,优先级比普通的后台线程要高,不容易被回收,适合执行一些高优先级的后台任务
- IntentService封装了HandlerThread和Handler
源码入下:
public abstract class IntentService extends Service {
private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler;
private String mName;
private boolean mRedelivery;
//自定义的Handler,这样可以把收到的任务消息发送给HandlerThread处理
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
//onHandleIntent处理具体的任务,运行在HandlerThread中
onHandleIntent((Intent)msg.obj);
//任务执行完毕会自动结束
stopSelf(msg.arg1);
}
}
public IntentService(String name) {
super();
mName = name;
}
public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
}
//第一次启动时会调用onCreate
@Override
public void onCreate() {
super.onCreate();
//创建HandlerThread
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
//调用HandlerThread的run方法,开启HandlerThread的消息循环,以便接收消息处理具体的任务
thread.start();
//获取HandlerThread的looper,创建ServiceHandler,这样通过ServiceHandler发送的消息最后都会在HandlerThread中处理
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
//每次调用IntentService都会执行onStartCommand方法,发送一个任务消息给HandlerThread处理,任务的信息通过Intent传递
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
@Override
public void onDestroy() {
mServiceLooper.quit();
}
@Override
@Nullable
public IBinder onBind(Intent intent) {
return null;
}
@WorkerThread
protected abstract void onHandleIntent(@Nullable Intent intent);
}
- IntentService通过Intent来传递任务参数,当任务执行完毕时会调用stopSelf(int startId)自己停止服务;
- IntentService的onHandleIntent是一个抽象方法,需要我们自己实现,用于处理具体的任务;
- 每执行一个后台任务就需要启动一次IntentService,IntentService内部通过消息的方式向HanderThread请求执行任务,Handler的Looper是顺序执行任务的,所以IntentService也是顺序执行后台任务的,因为Handler消息机制本身就只能串行的去执行任务;