IntentService解析

看其结构:

public abstract class IntentService extends Service{
...
}

抽象类,该类继承自Service,子类需要实现的抽象方法为:

protected abstract void onHandleIntent(Intent intent);

对该方法,有两个问题:

  1. 该方法在源码哪里被调用
  2. 参数是什么

通过搜索IntentService类在该类内部实现了一个内部类ServiceHandler

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);
        }
    }

该类继承自Handler,并在hanldeMessage(Message msg)方法中调用onHandleIntent(Intent intent)
并通过stopSelf(int startId)方法终止该Service。

经过测试,在调用stopSelf(int startId)去终结最近一个启动的Service时将会将Service销毁(调用到onDestroy()方法)。startId从1开始逐一增长,最大的ServiceId代表最近被start的service。以下为测试代码和Log结果:

 @Override
    public int onStartCommand(Intent intent, int flags, final int startId) {
        Log.e(TAG,"onStartCommand");
        Log.e(TAG,"intent:"+intent+" ,flags:"+flags+" ,startId:"+startId);
        //测试stopSelf(int starId)是否能停止特定的startId对应的Service
        //结果:能,但是当停止最近启动的ServiceId时将会销毁整个Service
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(5000);
                    Log.e(TAG,"启动的startId为:"+startId);
                    stopSelf(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        return super.onStartCommand(intent, flags, startId);
    }

测试stopSelf方法.png-28.8kB

也就是说IntentService在处理完onHanldeIntent()方法之后就销毁了。我看网上很多文章都说多次启动IntentService不会创建新的服务和新的线程,而实际上这是错误的理解。因为每次在调用完onHanleIntent方法之后该Service就已经被销毁,多次启动将会多次调用Service的onCreate方法去重新初始化Service。那就意味着我们在处理多任务时需要在onHandleIntent()方法中自定义队列或者循环去发送事件。

那么以上我们了解了处理事件的方法onHandleIntent(Intent intent)是在handler类中进行调用,那么发送这个Message的handler绑定了哪个线程,又是在哪里进行发送的呢?
我们找到ServiceHandler的对象mServiceHandler,可以看到它是在Service类中的onCreate方法中进行初始化:

@Override
    public void onCreate() {
        // TODO: It would be nice to have an option to hold a partial wakelock
        // during processing, and to have a static startService(Context, Intent)
        // method that would launch the service & hand off a wakelock.

        super.onCreate();
        //初始化HandlerThread并启动该线程
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

        mServiceLooper = thread.getLooper();
        //初始化mServiceHandler
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

在HandlerThread中初始化了该Thread对应的Looper,mServiceHandler对象通过该Looper绑定该HandlerThread作为工作线程将需要工作的内容发送到handleMessage()方法中进行处理,这就是为什么说IntentService能够异步处理数据,且不需要在处理耗时任务时自定义线程去处理。

我们知道通过startService启动Service调用的生命周期是onCreate->onStartCommand->onDestroy,而发送工作内容的代码就是在IntentService的onStartCommand方法中调用onStart方法实现(现在onStart()方法已被标记为弃用):

@Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

@Override
    public void onStart(Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }    

很普通的通过hanlder发送消息的代码,将intent封装到message.obj中发送到Handler的实现类ServiceHandler中去处理。

由此我们可以看到,onHandleIntent(Intent intent)方法中的intent参数就是onStartCommand中的Intent参数,也就是我们通过starService启动的Intent参数,而每次我们通过startService方法启动IntentService实现类就和启动普通的Service类一样,调用到onStartCommand生命周期方法,然后在该方法中通过handler发送Intent到handleMessage方法中进行处理,最后在handleMessage()方法中调用抽象方法onHandleIntent(Intent intent)方法,该方法在IntentService类中暴露给用户去实现。

观察到IntentService在销毁Service时调用了Looper.quit()方法。

@Override
    public void onDestroy() {
        mServiceLooper.quit();
    }

很好地实现了对Looper生命周期的设计,很多时候我们会忘记这些细节,而HandlerThread中绑定并启动Looper的代码在HandlerThread的run()方法中实现,一个标准的启动Looper代码:

@Override
    public void run() {
        mTid = Process.myTid();
        //初始化Looper对象,初始化MessageQueue对象,关联当前线程
        Looper.prepare();
        synchronized (this) {
        //获取当前线程绑定的Looper
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        //HandlerThread类中留给子类去实现的空方法,目的是为了让子类做一些在Looper开始loop前的工作
        onLooperPrepared();
        //开启loop无限循环作业,处理MessageQueue中存储的的message
        Looper.loop();
        mTid = -1;
    }

你可能感兴趣的:(android,android)