IntentService与HandlerThread源码解析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/pihailailou/article/details/78838246

一,写在前面

       IntentService使用场景:需要在服务中执行耗时的任务,使用IntentService代替在Service中开启子线程。
       HandlerThread:封装了Thread+Looper,但并没有封装Handler。它是一个线程,run方法中初始化了Looper对象,并开启消息循环。
       IntentService:封装了HandlerThread+Handler的Service。
       在阅读本篇文章前,建议先了解Handler机制的工作原理,本篇将不再对重复内容进行阐述。可参考文章 

二,使用IntentService

        直接上代码,IntentService是一个抽象类,首先创建一个它的子类:

public class MyIntentService extends IntentService {

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

	@Override
	protected void onHandleIntent(Intent intent) {
		SystemClock.sleep(3000);
		String stringExtra = intent.getStringExtra("key");
		SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd hh:MM:ss");
		String time = format.format(new Date(System.currentTimeMillis()));
		Log.e("wcc", "onHandleIntent _ " + stringExtra + ", time is " + time);
	}
	
	@Override
	public void onCreate() {
		super.onCreate();
		Log.e("wcc", "onCreate");
	}

	@Override
	public void onStart(Intent intent, int startId) {
		super.onStart(intent, startId);
		Log.e("wcc", "onStart");
	}
	
	@Override
	public void onDestroy() {
		super.onDestroy();
		Log.e("wcc", "onDestroy");
	}
}
       接下来是启动服务的代码:

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		Intent intent = new Intent(this, MyIntentService.class);
		intent.putExtra("key", "value1");
		startService(intent);
		
		intent.putExtra("key", "value2");
		startService(intent);
	}
}

       启动了两次服务,每次存储在extra中的值都不一样。在onHandleIntent方法中执行耗时操作,并在各个生命周期方法中打印log。

       打印log如下:


       启动两次服务,onStart调用两次,onHandleIntent方法被调用两次且间隔3秒,最后onDestroy也被调用。为了解释上面这一现象,下面开始从源码角度分析IntentService工作原理。


三,HandlerThread源码分析

public class HandlerThread extends Thread {

    //...code

    @Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }

    //...code

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

    //...code

}
       第8行,初始化Looper对象,并使用ThreadLocal存储该子线程的Looper。
       第10行,从ThreadLocal中取出该线程的Looper对象,并赋值给变量mLooper。
       第15行,调用Looper.loop()方法开启消息循环。
       第21行,调用HandlerThread$getLooper返回变量mLooper,也就是获取该线程的Looper对象。
       (对ThreadLocal,Looper不了解可以查看前面推荐的参考文章,这里不再重复描述)

       小结:从上面可以看出,HandlerThread并不像名称展现的那样,它并没有封装Handler,而是封装了Thread,Looper。也就是说,HandlerThread是一个开启了消息循环的子线程。
       注意:使用HandlerThread时,若不需要HandlerThread的时候,可以调用HandlerThread的quit/quitSafely方法结束消息循环,从而终止线程的执行。关于结束消息循环的原理,见文章  Android中Looper,MessageQueue,ThreadLocal源码解析 ,这里不再重复阐述。

四,IntentService源码分析

       在调用startService启动服务的时候,会调用onCreate,onStart方法。
       查看IntentService$onCreate,IntentService$onStart方法相关的源码:
    @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);
    }

    @Override
    public void onStart(Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }
       第8行,创建HandlerThread对象,它是一个开启了消息循环的子线程。
       第9行,调用HandlerThread$start方法启动线程,HandlerThread$run方法被调用,前面已对该方法进行分析,这里不再重复阐述。
       第11行,获取HandlerThread中的Loooper对象,是一个子线程中的Looper对象。
       第12行,创建一个变量mServiceLooper构造的Handler对象。
       
       第17~19行,创建Message对象并设置字段arg1,obj的值;
       第20行,使用Handler$sendMessage方法发送消息;

       于是,查看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);
        }
    }
       第3行,调用Handler中Looper为参数的构造函数;
       第8行,调用IntentService$onHandleIntent方法;
       第9行,调用IntentService$stopSelf方法,停止服务,回调onDestroy方法。

       查看IntentService$onHandleIntent方法源码:
protected abstract void onHandleIntent(Intent intent);
       onHandleIntent是一个抽象方法,需要我们自己重写该方法,并将耗时操作放在里面。

       那么onHandleIntent为啥能执行耗时操作呢?
       通过对Handler机制的理解可以知道:调用Looper$loop方法取出消息队列里的消息,并处理消息。因此消息的处理在哪个线程中完成取决于Looper.loop()在哪被调用,前面我们知道Looper的初始化,以及开启消息循环都是在子线程HandlerThread的run方法中完成。于是消息的处理是在子线程中执行,onHandleIntent就可以执行耗时操作。

五,最后

       可以发现IntentService通过Handler机制将任务的执行,由主线程切换到Looper所在的子线程中执行。
       
       若调用多个startService启动多个耗时任务,由于内部实现基于Handler机制,Looper是按照顺序来处理消息,因此这些耗时任务将按照启动的顺序依次执行。
       
       另外,在handleMessage方法里调用stopSelf(startId)来停止服务,此外还有一个重载方法stopSelf()。区别:stopSelf(startId)停止服务,会等待消息队列里的消息全部处理完毕,再停止服务;而stopSelf()会立刻停止服务。
       




       
       






扫描二维码关注公众号,回复: 3319950 查看本文章

       

猜你喜欢

转载自blog.csdn.net/pihailailou/article/details/78838246