看其结构:

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

也就是说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;    }

更多相关文章

  1. 使用Android(安卓)Camera2 API获取YUV数据
  2. sqlite 中判断某个表是否存在的方法
  3. android 调用视图报错The specified child already has a parent
  4. Android导入项目出现“R cannot be resolved to a variable"错误
  5. Android(安卓)相对布局中的 代码中修改属性与布局文件的设置不同
  6. Android学习笔记(二)——Android的数据存储(一)SharedPreferences
  7. Android(安卓)WebView 踩过的坑
  8. Fragment使用
  9. Android(安卓)N 各种ANR的时间

随机推荐

  1. sqlite迁移到mysql脚本的方法
  2. mysql分页时offset过大的Sql优化经验分享
  3. MySQL5.7.18主从复制搭建(一主一从)教程
  4. Mysql5.7.18的安装与主从复制图文详解
  5. Mysql5.7.14 linux版密码忘记完美解决办
  6. mysql函数拼接查询concat函数的使用方法
  7. 解决MYSQL连接端口被占引入文件路径错误
  8. windows server 2008 64位MySQL5.6免安装
  9. 2017最新版windows安装mysql教程
  10. Mysql使用insert插入多条记录 批量新增数