Android之IntentService使用及源码分析

这篇文章带着大家掌握IntentService的使用,以及从源码角度去理解IntentService是如何工作的。

IntentService的使用场景:当我们需要在Service中开启子线程去完成异步任务时,可以在Service中创建子线程处理;也可以使用封装了Service+Thread的IntentService,具体后面会详细介绍。

例如:接受广播时,可能需要执行耗时操作,由于广播的生命周期很短,在onReceive()方法执行完就结束了。这时,可能出现广播已经销毁,但线程里的代码还没有执行完,线程会继续执行,但该线程所在的宿主进程由于广播组件的销毁,变为了空进程。根据进程优先级,在内存不足时,空进程是很容易被系统杀死的。于是,可以在广播中开启一个服务,在服务里开启子线程执行异步任务。

首先,学习IntentService的使用,如下:

依次启动三个服务

	Intent intent = new Intent(this,MyIntentService.class);
	intent.putExtra("extra", "extra_1");
	startService(intent);
	
	intent.putExtra("extra", "extra_2");
	startService(intent);
	
	intent.putExtra("extra", "extra_3");
	startService(intent);
public class MyIntentService extends IntentService {

	public MyIntentService() {
		super("");
	}

	@Override
	protected void onHandleIntent(Intent intent) {
		SystemClock.sleep(3000);
		String strExtra = intent.getStringExtra("extra");
		Date date = new Date(System.currentTimeMillis());
		SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
		Log.e("", "MyIntentService : " + strExtra + ",time:" + sdf.format(date));
	}
	
	@Override
	public void onDestroy() {
		super.onDestroy();
		Log.e("", "MyIntentService  destroy");
	}

}
执行后打印日志如下:

05-31 14:33:31.074: E/(10792): MyIntentService : extra_1,time:17-05-31 14:33:31
05-31 14:33:34.076: E/(10792): MyIntentService : extra_2,time:17-05-31 14:33:34
05-31 14:33:37.078: E/(10792): MyIntentService : extra_3,time:17-05-31 14:33:37
05-31 14:33:37.080: E/(10792): MyIntentService  destroy
分析:每隔三秒就完成一次异步任务,是顺序执行的,extra1 - extra2 = extra3,最后才被destroy了。
重写onHandleIntent方法,在里面执行耗时操作,参数intent就是启动服务startService中的intent传递过来的。

接下里,从源码角度分析IntentService是如何一步步工作的。IntentService是着这样继承关系:public abstract class IntentService extends Service

启动服务,会调用onCreate(),onStartCommand(),onstart(),   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 thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }
分析:进入HandlerThread类查看源码,public class HandlerThread extends Thread,HandlerThread就是线程Thead的一个子类。
thread.start();启动一个子线程,会调用HandlerThread的run()方法。run()的源码如下:

@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.loop()两个方法,于是子线程中的Looper初始化了。调用HandlerThread.getLooper()可以获取子线程的Looper。

所以,OnCreate中的mServiceLooper = thread.getLooper()就是得到创建好的子线程的Looper对象。

OnCreate中的mServiceHandler = new ServiceHandler(mServiceLooper),是创建一个Handler实例,且传入Looper对象作为参数。一般情况下,我们在创建Handler对象的时候是不会传入Looper参数,例如:在主线程中创建Handler对象,Handler h = new Handler()。在文章“全面解析Android之Handler机制”中讲过:创建Handler对象必须初始化线程的Looper,否则会报错,以及主线程直接创建Handler对象不会出错的原因,这里不再过多描述。

如果实例化Handler传入了Looper对象,那么Handler就在该Looper所在线程中处理消息;如果没有传入Looper对象,默认是在Handler所在的线程中处理消息,而且线程里必须初始化Looper,否则创建Handler对象会报错。

onCreate总结:开启了一个HandlerThread的子线程,并初始化了该子线程中的Looper;创建Handler对象时,传入该Looper作为构造函数参数。

继续查看onStartCommand(),onStart()的源码,如下:

/**
     * You should not override this method for your IntentService. Instead,
     * override {@link #onHandleIntent}, which the system calls when the IntentService
     * receives a start request.
     * @see android.app.Service#onStartCommand
     */
    @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);
    }
分析:onStartCommand()里面调用了onStart(),在onStart()中HandlerThread调用sendMessage(..)发送消息,源码中消息处理如下:

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);
        }
    }
分析:onHandleIntent((Intent)msg.obj):完成消息的处理,在里面执行异步任务。该方法是一个抽象方法,需要在继承IntentService的时候重写,且是在Looper所在的线程中执行,这个线程是HandlerThread创建的一个子线程。

stopSelf(msg.arg1):用于在onHandleIntent执行完消息处理后,停止服务。实际上,IntentService中还有一个空参stopSelf()停止服务,区别就是空参会立刻停止服务,而stopSelf(msg.arg1)会让消息队列里的消息全部处理完后,才停止服务。

注:文章开头说的IntentService封装了Service+Thread,事实上是不准确的,应该是封装了Service + HandlerThread + Handler机制。

本篇文章没有对Handler机制中发送消息,处理消息涉及的MessageQueue,Looper的原理进行过多描述,有需要的同学可以参考小王君的博客“全面解析Android之Handler机制”。在该文章中小王君对Handler机制从源码的角度进行了极为细致解读,并列出了在开发中使用的几种场景代码,相信读者阅读该文章是可以透彻理解Android的Handler机制的!

最后,辛苦大家能看到这里,文章有不够准确的地方,期待大家能在下面评论中指出,一起学习进步!!!

———小王君       (*^__^*) 




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值