原来模式
我们知道Service是运行在主线程里的,因此,如果在服务里面执行耗时代码操作,我们需要开启一个子线程去处理这些代码。比如我们可以在onStartCommand
方法里面去开启子线程来处理耗时代码。
public int onStartCommand(Intent intent, int flags, int startId) {
Thread thread = new Thread(){
@Override
public void run() {
/**
* 耗时的代码在子线程里面写
*/
}
};
thread.start();
return super.onStartCommand(intent, flags, startId);
}
但是,我们都知道,服务一旦启动,就会一直运行下去,必须调用stopService()或者stopSelf()方法才能让服务停止下来。所以,我们来修改一下run方法
public void run() {
/**
* 耗时的代码在子线程里面写
*/
stopSelf();
}
}
就这样,我们很容易的就在服务里面开启了一个线程,然后在代码最后面加上stopSelf();这样就可以在代码运行结束的时候,结束服务了。但是这样对于我们开发者来说,是不是有些麻烦呢,确实有点麻烦,比如你有时候忘记了开启线程呢?或者忘记了调用stopSelf()?
所以,谷歌给我们一个很好的类,通过这个类我们就可以不用管这些东西,因为这个类已经帮我们实现了在子线程中操作代码了。同时,但子线程代码执行完毕,这个服务会自动销毁,不用再占用内存资源。所以,我们通过这个类,就可以不用去开启线程,也不用去销毁这个服务。因为,这个类都帮我们处理好了。这个类就是IntentService。这个类的使用和Service大同小异,但是比Service更加省心,更加方便。下面我们直接看代码吧,我习惯在代码中讲解。
IntentService源码
/**
* IntentService是一个以{@linkService}的为基类来处理异步请求的类
* 客户端发送请求通过{@link android.content.Context *#startService(Intent)}调用;
* 该服务根据需要启动,使用worker线程依次处理每个Intent线程,并在run工作完成时自行停止本service。
*
* <p>这种“工作队列处理器”模式通常用于卸载任务
*来自应用程序的主线程。 IntentService类存在于
*简化这种模式并处理机制。要使用它,请扩展
* IntentService并实现{@link #onHandleIntent(Intent)}。 IntentService
* 将接收Intents,启动工作线程,并停止服务
*合适。
*
* <p>所有请求都在一个工作线程上处理 - 它们可以作为
*尽可能长(并且不会阻止应用程序的主循环),但是
*一次只能处理一个请求。
*
*/
public abstract class IntentService extends Service {
//开启线程的Looper
private volatile Looper mServiceLooper;
//用于发送和处理消息的handler
private volatile ServiceHandler mServiceHandler;
//子线程的名称
private String mName;
//是否可重复发送
private boolean mRedelivery;
//处理消息handler的实现
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
//子线程
//抽象方法 留给子类去重写
onHandleIntent((Intent)msg.obj);
// 子线程任务执行完了,停止本service
stopSelf(msg.arg1);
}
}
/**
* 构造函数
* @param name worker线程的名字 对调试有用
*/
public IntentService(String name) {
super();
mName = name;
}
/**
*
* Sets intent redelivery preferences. Usually called from the constructor
* with your preferred semantics.
* 设置intent重发偏好,通常在构造函数调用
*
*
* 如果设置是true,{@link #onStartCommand(Intent, int, int)} 将返回{@link Service#START_REDELIVER_INTENT}
* 因此,如果这个进程在onHandleIntent返回之前死掉了,那么进程将会被重启,并且发送此intent
* 如果多个intents被发送,只有最近的一个会被确保重新发送
*
* 如果设置为false,{@link #onStartCommand(Intent, int, int)} 将返回{@link Service#START_NOT_STICKY}
* 如果这个进程死掉了,那么这个intent就死掉了
*
*/
public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
}
@Override
public void onCreate() {
super.onCreate();
//使用HandlerThread开启一个线程,并产生looper和消息队列
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
//获取上述子线程的looper
mServiceLooper = thread.getLooper();
//初始化 handler
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public void onStart(Intent intent, int startId) {
//onstart时发送一个消息给handle
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;
}
@Override
public void onDestroy() {
mServiceLooper.quit();
}
/**
* Unless you provide binding for your service, you don't need to implement this
* method, because the default implementation returns null.
* @see android.app.Service#onBind
*/
@Override
public IBinder onBind(Intent intent) {
return null;
}
/**
* 这个方法在子线程中执行,一次只能执行一个事件,
*/
@WorkerThread
protected abstract void onHandleIntent(Intent intent);
}
总结:使用IntentServices
是使用Service+ HandlerThread
的方式,很多情况下我们可以使用HandlerThread+ handler
来进行线程执行和handler分发消息。