IntentService
IntentService继承自Service,可以处理异步的请求(通过intent传递参数).客户端通过startService(intent)来发送请求,service开始之后在线程里按顺序处理每一个intent,当它运行完所有任务之后会自动停止。
如何使用:继承IntentService,实现onHandleIntent(Intent)这个方法,intentService会接受intents,启动一个工作线程,在合适的时候停止这个service。
所有的请求都在一个工作线程里边被处理,他们可以长时间运行而且不会阻塞应用的主线程,但是同时只能处理一个请求。
首先来看onCreate方法
onCreate里生成一个HandlerThread,并通过start()启动该线程,然后生成一个ServiceHandler
@Override
public void onCreate() {
/* TODO:最好在这有一个处理部分wakelock(这个坑先留着)的选项,
而且应该有一个静态的startService(context,intent)方法启动service同时切换wakelock */
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
这是生成的线程中处理消息的Handler(私有final内部类)
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
/*通过这里可以看到,当声明的线程里边相关联的MessageLooper里边message被处理完毕之后就会停掉整个service*/
stopSelf(msg.arg1);
}
}
onHandleIntent是个抽象方法需要被子类实现,来进行那些需要在非UI线程执行的代码
/**
这个方法是在工作线程中被调用,并且传递了相关的请求参数,同一时间只有一个intent被处理,
但是这个过程是在一个单独的工作线程中运行,所以,如果这些代码长时间运行的话,它会阻塞其他发送到这个intentservice中的请求,
当所有请求都被处理之后intentserice会停掉自己,所以不要手动调动stopSelf.
这个方法中的intent参数就是startService(intent)中的参数
*/
protected abstract void onHandleIntent(Intent intent);`
在onStart里边将intent和startId发送到MessageLooper里边处理,也就是在onHandleIntent中处理
@Override
public void onStart(Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
/**
不要重写此方法,
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
/**设置为true,onStartCommand()会返回START_REDELIVER_INTENT,
然后如果进程在onHandleIntent()返回之前死掉了,进程会重新启动同时intent会被重新传入,
如果提交了多个intents,只有最近的那个可以保证重新传入
设置为false,onStartCommand()返回START_NOT_STICKY,如果进程死掉,intent也就陪葬了
*/
public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
}
onStartCommand中返回值含义:
1 | /* |
IntentService的onDestroy退出looper
@Override
public void onDestroy() {
//Looper退出
mServiceLooper.quit();
}
HandlerThread
在IntentService中的工作线程是通过HandlerThread实现,HanderThread是一个拥有looper的线程,这个looper可以用来创建Handler类,start()方法必须被调用。
public HandlerThread(String name) {
super(name);
//赋予默认的线程优先级
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
/**
这个优先级必须是来自Process,不能是Thread
*/
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {//做了同步处理
mLooper = Looper.myLooper();
//这个notifyAll会唤醒等待获取looper的方法(getLooper()中)
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
在run里边将该线程初始化为Looper,设置优先级,然后循环message队列
/**
回调方法:在looper loops之前的一些准备操作可以通过重写这个方法来完成
*/
protected void onLooperPrepared() {
}
Handler退出Looper
/**
退出handler线程的looper
调用这个方法会中断handler thread的looper,使message queue里边的所有message都不再运行
在looper被停止之后,任何尝试提交给queue的messages都会失败
调用这个方法有时不安全,因为有些message在looper中断之前不会再被传递,
考虑使用quitSafely来代替以确保所有待执行的任务有序的执行
*/
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}`
/**
安全的退出handler线程的looper
当所有在messagequeue里边的messages都被执行之后handler线程的looper才会中断,
那些延迟执行messages的都不会再执行
*/
public boolean quitSafely() {
Looper looper = getLooper();
if (looper != null) {
looper.quitSafely();
return true;
}
return false;
}
/**
返回这个线程关联的looper
如果线程没有开始或因为某些原因isAlive()returns false,这个方法会返回null,
如果这个线程已经开始,这个方法会阻塞直到looper被初始化
*/
public Looper getLooper() {
if (!isAlive()) {
return null;
}
// 如果这个线程已经开始,这个方法会阻塞直到looper被初始化
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
综上呢,IntentService继承制Service,内部通过HandlerThread来创建线程和在该线程中生成的Looper完成Handler的消息处理,处理完毕所有通过startService中传入的intent之后就会结束自己。可以通过重写IntentService的onStart方法来改变handler处理message的方式,比如延时。