IntentService是一个专门用来处理异步线程的一个服务,它内部创建了一个消息队列以及一个Handler对象,其它组件将Intent发送过来之后,IntentService会将这个Intent通过消息队列发送到工作线程,所以,我们可以放心大胆的在IntentService内部做耗时操作,而不必单独开启线程。
好,大概描述了下,我们看一下它的实现方式:
package android.app;
import android.annotation.WorkerThread;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
...
public abstract class IntentService extends Service {
private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler;
private String mName;
private boolean mRedelivery;
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
}
...
public IntentService(String name) {
super();
mName = name;
}
...
public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
}
@Override
public void onCreate() {
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@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;
}
@Override
public void onDestroy() {
mServiceLooper.quit();
}
...
@Override
public IBinder onBind(Intent intent) {
return null;
}
...
@WorkerThread
protected abstract void onHandleIntent(Intent intent);
}
将注释代码删除掉之后,真正的实现代码很少,现在将对这些代码一一说明,首先是onCreate方法:
onCreate方法主要做了以下事情:
创建HandlerThread线程并启动,使用HandlerThread对象所创建的Looper对象初始化ServiceHandler对象,这样,就可以通过ServiceHandler对象HandlerThread中的消息队列发送数据了,我们看看他们之间是如何实现的,首先是HandlerThread:
...
package android.os;
...
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() {
}
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
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;
}
}
这个中的代码也不多,我们看主要的run方法:
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
run方法主要做了以下事情:
调用Looper.prepare();在当前线程中初始化一个Looper消息循环对象,并初始化了一个消息队列,拿到这个线程的Looper对象,然后开启消息循环访问模式。
接着回到IntentService的onCreate方法中,使用刚才的工作线程中的Looper对象来初始化ServiceHandler,使mServiceHandler对象向这个线程的Looper中发送消息。
准备工作做好之后,接下来的逻辑就简单了,其它组件通过startService方法,将Intent传递到这个服务中,会调用onStartCommand方法,onStartCommand调用onStart方法,而onStart方法会将接收到的Intent对象作为被传送的消息实体通过ServiceHandler发送到工作线程,然后我们如果使用的话,直接重写onHandleIntent就可以,onHandleIntent收到对象的时候已经处在工作线程当中。
我们在onHandleIntent方法中处理完毕任务之后,不必手动去调用stopSelf去停止服务,IntentService已经帮我们做了这样的处理。说到这里,可能你会有疑问,如果我在很短的时间内发送了多个请求,那么第一个请求处理完毕那服务不就终止了吗,后面的怎么处理呢,对于这个问题,需要详细了解一下stopSelf的说明:
如果我们现在工作在默认模式,同一时间只有一个Intent会被处理,如果在当前这个任务处理结束之前还有一个Intent请求过来的话,那它就不会被终止,它的原因与stopSelf有关系,stopSelf会判断终止的startId是否是最后发送过来的startId,所以,疑问解决了。
到这里基本的解释就说完了,有疑问欢迎留言。