IntentService源码实例讲解

来源:互联网 发布:office2007办公软件 编辑:程序博客网 时间:2024/06/18 14:22

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算是讲完了,大家都基本理解了没,欢迎提问交流。 


原创粉丝点击