IntentService源码实例讲解

service的基本使用基本大家都学习过, 也大概用过,
比如startService(), stopService(), bindService, unbindService();
比如调用startService的Activity一旦销毁, 那么Service可能处于不可管控状态;
又比如Service中要想做一些耗时任务, 必须要自己启动线程, 或者还得要使用线程池。

那么是不是可以有这么一个东西, 它既可以有service的一些优点, 对service的缺点也做出了优化呢? 
YES, IntentService就做到了, 它的内部使用了HandlerThread同时配合handler来
实现了在service中可以做耗时操作;
相应的task完成之后, service也做到了自动终结, 无须开发者手动终止service.

下面来看看IntentService的源码吧:

public abstract class IntentService extends Service {
首先它是继承自Service, 同时还是个抽象类, 估摸着在用它的时候是不是还得重写它的方法?①


(1)从Service的角度来看,无论咋样,应该都是有onCreate(), onStartCommand(), onBind(), onDestroy()这些方法的,
那么先来看看onCreate()吧:

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(Thread,Loop结合体),并通过thread的Looper创建了Handler,
也就是说在onCreate()中,创建了子线程,同时基于子线程创建了Handler处理消息;

(2)看看onStartCommand()方法吧
public int onStartCommand(Intent intent, int flags, int startId) {
    onStart(intent, startId);
    return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}

其中调用了onStart(intent, startId)方法;
public void onStart(Intent intent, int startId) {
    Message msg = mServiceHandler.obtainMessage();
    msg.arg1 = startId;
    msg.obj = intent;
    mServiceHandler.sendMessage(msg);
}

在其中创建了Message,并将intent,startId作为msg的成员;将该Message发给Handler处理;
具体看看Handler怎么处理吧:


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方法处理该Message消息;
第二步:调用stopSelf(msg.arg1),在消息队列中没有消息的时候,结束当前service

好,先从onHandleIntent((Intent)msg.obj)看起,发现这个是个抽象函数,那么这个
就应该是本文开头所说的继承IntentService所需要重写的方法了。
由于IntentService的onCreate()方法里面创建了子线程,子线程内部又创建了Handler,
那么onHandleIntent方法中自然就可以做一些耗时操作了。

那么再所说stopSelf(msg.arg1),在原先Service中,我们需要停掉startService启动
的Service的话,需要调用stopService()或者stopSelf(),
其实stopSelf() 内部也是调用stopSelf(int startId),只不过传入的参数为-1罢了。
public final void stopSelf(int startId) {
    if (mActivityManager == null) {
        return;
    }
    try {
        mActivityManager.stopServiceToken(
                new ComponentName(this, mClassName), mToken, startId);
    } catch (RemoteException ex) {
    }
}

内部具体调用,如果handler内部消息队列中没有消息需要处理,就终止Service,
如果其中还有消息需要处理,则让Handler处理消息,消息都处理完在终止该Service.
对于Framework不了解的同学,后面我会在案例中进行验证:②

(3)再来说说onBind(),这里重写了Service的onBind()并直接返回null
那么就可以看出,IntentService在设计之初就不考虑支持bindService,unbindService()的,
另外bindService的调用流程,也不会走onStartCommand()方法,这与IntentService设计理念不吻合,
所以如果在IntentService中重写onBind(),并通过bindService来绑定服务的话,那么IntentService与
普通Service是没有区别的,也体现不出IntentService的优势。

(4)最后说下onDestroy()
其中只有一行代码:mServiceLooper.quit();
即将onCreate()中HandlerThread中的loop循环停止,即handler停止工作,onCreate()中
创建的HandlerThread停止工作,整个Service终止。

(5)对几处疑问点做实例说明:

先附上Service部分的代码:

package intentservice.cn.example.com.intentservicetest;

import android.app.IntentService;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

public class MyIntentService extends IntentService {
    public static final String TAG = "MyIntentService";
    //在注册Service的时候会提醒添加默认构造函数,否则运行崩溃,我也是实际运行时才发现
 
 
    public MyIntentService() {
        super("MyIntentService");
    }
public MyIntentService(String name) {
	super(name);    
    }   
    @Override    
    public void onCreate() {        
	Log.d(TAG, "onCreate");        
	super.onCreate();    
    }    
    @Override    
    public int onStartCommand(Intent intent, int flags, int startId) {        
        Log.d(TAG, "onStartCommand");        
	return super.onStartCommand(intent, flags, startId);    
    }    
    @Override    
    public void onStart(Intent intent, int startId) {        
	Log.d(TAG, "onStart,send msg to handler");        
	super.onStart(intent, startId);    
    }    
    @Override    
    protected void onHandleIntent(Intent intent) {        
	Log.d(TAG, "onHandleIntent invoked by handler. begin.");        
	//模拟耗时任务        
	try {            
	    Thread.sleep(2000);        
	} catch (InterruptedException e) {            
	    e.printStackTrace();        
	}        
	Log.d(TAG, "onHandleIntent invoked by handler. end.");    
    }    
    @Override    
    public IBinder onBind(Intent intent) {        
	Log.d(TAG, "onBind");        
	return super.onBind(intent);    
    }    
    @Override    
    public void onDestroy() {        
	Log.d(TAG, "onDestroy");        
	super.onDestroy();    
    }
}
 
 

①连续多次StartService的时候,IntentService的生命周期流程:

Intent service = new Intent(this, MyIntentService.class);
startService(service);
startService(service);


日志:
11-26 06:34:13.584 D/MyIntentService( 2998): onCreate
11-26 06:34:13.589 D/MyIntentService( 2998): onStartCommand
11-26 06:34:13.589 D/MyIntentService( 2998): onStart,send msg to handler
11-26 06:34:13.590 D/MyIntentService( 2998): onStartCommand
11-26 06:34:13.590 D/MyIntentService( 2998): onStart,send msg to handler
11-26 06:34:13.591 D/MyIntentService( 2998): onHandleIntent invoked by handler. begin.
11-26 06:34:15.592 D/MyIntentService( 2998): onHandleIntent invoked by handler. end.
11-26 06:34:15.593 D/MyIntentService( 2998): onHandleIntent invoked by handler. begin.
11-26 06:34:17.594 D/MyIntentService( 2998): onHandleIntent invoked by handler. end.
11-26 06:34:17.596 D/MyIntentService( 2998): onDestroy

可见Service中是异步处理消息的,同时这种情况下onCreate()只执行一次,onStartCommand的次数跟startService次数一样。

另外,只有消息队列中所有msg都处理结束的时候,onDestroy()才会执行。

②第一次StartService中task完成后,过一段时间再次StartService,IntentService的生命周期流程:

final Intent service = new Intent(this, MyIntentService.class);
startService(service);
new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        startService(service);
    }
}).start();


日志:

11-26 06:18:25.373 D/MyIntentService( 2998): onCreate
11-26 06:18:25.384 D/MyIntentService( 2998): onStartCommand
11-26 06:18:25.385 D/MyIntentService( 2998): onStart,send msg to handler
11-26 06:18:25.385 D/MyIntentService( 2998): onHandleIntent invoked by handler. begin.
11-26 06:18:27.387 D/MyIntentService( 2998): onHandleIntent invoked by handler. end.
11-26 06:18:27.389 D/MyIntentService( 2998): onDestroy
11-26 06:18:28.252 D/MyIntentService( 2998): onCreate
11-26 06:18:28.255 D/MyIntentService( 2998): onStartCommand
11-26 06:18:28.256 D/MyIntentService( 2998): onStart,send msg to handler
11-26 06:18:28.257 D/MyIntentService( 2998): onHandleIntent invoked by handler. begin.
11-26 06:18:30.258 D/MyIntentService( 2998): onHandleIntent invoked by handler. end.
11-26 06:18:30.260 D/MyIntentService( 2998): onDestroy


很明显,第二次startService的开始时间是在第一次startService中的task完成之后,

所以第一次startService中的task完成之后,发现队列中并没有其他msg需要处理,所以直接调用onDestroy()了。

这种情况下,service生命周期都会重新执行,包括其中handler,thread等。

实验过程中:别忘了注册Service哈!!

好了,IntentService算是讲完了,大家都基本理解了没,欢迎提问交流。 


猜你喜欢

转载自blog.csdn.net/u012989337/article/details/78637557