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方法主要做了以下事情:
创建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; } }
@Override public void run() { mTid = Process.myTid(); Looper.prepare(); synchronized (this) { mLooper = Looper.myLooper(); notifyAll(); } Process.setThreadPriority(mPriority); onLooperPrepared(); Looper.loop(); mTid = -1; }
调用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,所以,疑问解决了。
到这里基本的解释就说完了,有疑问欢迎留言。