IntentService
概述
它是Service的子类,与普通Service相比,它具有如下优点:内部维护了一个线程,因此可以直接在onHandleIntent()方法中访问网络,而不需要再开线程;会将所有的启动该Service的Intent对象存储进来,然后依次执行,并且在执行完毕后,会调用stopSelf(),不需要自己处理。重写了onBind(),并返回null。
它的缺点也在于,当我们要绑定服务时,不能使用该类。
因此,当只需要Service去在后台联网获取数据时,直接继承IntentService,然后在onHandleIntent中处理联网逻辑即可。
源码及分析
public abstract class IntentService extends Service {
private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler;
private String mName;
private boolean mRedelivery;
//首先定义了一个Handler的子类
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);//当handler接收到消息时,会调用onHandleIntent(),这也是唯一要重写的方法
stopSelf(msg.arg1);//请求处理完成后,自己停止
}
}
/**
* @param name Used to name the worker thread。用来为当前的工作线程命名
*/
public IntentService(String name) {
super();
mName = name;
}
/**
* 它影响onStartCommand()的返回值
*/
public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
}
/*
* 在TA中创建一个Handler对象,因此当TA中有新消息时,便调用Handler的hanldMessage()。
* 并且由于handler是创建在子线程中的,所以hanldMessage()和onHandleIntent运行在子线程中。
*/
public void onCreate() {
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();//当前的Service被创建时就启动了一个新的线程,记为TA
mServiceLooper = thread.getLooper();//得到TA中的Looper对象
mServiceHandler = new ServiceHandler(mServiceLooper);
}
// 从这里可以看出,所有启动该Service的Intent对象都将存储在MessageQueue中。
public void onStart(Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);//Service一开始,便会往MessageQueue中发送消息,从而会执行onHandleIntent
}
/**
* 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 onDestroy() {//服务销毁时,也就结束Looper的loop
mServiceLooper.quit();
}
/**
* Unless you provide binding for your service, you don't need to implement this
* method, because the default implementation returns null.
* @see android.app.Service#onBind
*/
@Override
public IBinder onBind(Intent intent) {
return null;
}
/**
* 这个方法是我们唯一要重写的,用来处理联网逻辑的地方。
* This method is invoked on the worker thread with a request to process.
* Only one Intent is processed at a time, but the processing happens on a
* worker thread that runs independently from other application logic.
* So, if this code takes a long time, it will hold up other requests to
* the same IntentService, but it will not hold up anything else.
* When all requests have been handled, the IntentService stops itself,
* so you should not call {@link #stopSelf}.
*
* @param intent The value passed to {@link
* android.content.Context#startService(Intent)}.
*/
protected abstract void onHandleIntent(Intent intent);
}
补充
Service的生命周期中有onStartCommand(Intent , int , int )方法,它会调用Service.onStart(),只不过后者已经过时,所以建议重写onStartCommand()。
当组件通过startService()启动Service时,系统会自动调用onStartCommand()。因此在IntentService中,每一个启动当前Service的Intent都会被存储到MessageQueue中。并且每一次调用onStartCommand()传入其中的startId都会不同。
服务的类型由onStartCommand()的返回值决定。常用的类型有:START_NOT_STICKY,START_STICKY和START_REDELIVER_INTENT。把返回START_REDELIVER_INTENT和START_NOT_STICKY的服务称为non-sticky服务(IntentService就属性该种服务),返回START_STICKY称为sticky服务。
对于non-sticky服务来说,会在服务认为自己已完成任务时停止。而sticky却会一直运行下去,直到外部某组件调用了stopService()为止。
如果系统需要在服务完成任务之前关闭它,START_NOT_STICKY会被关闭,而START_REDELIVER_INTENT则会在可用资源不再吃紧时,尝试再次启动。
对于IntentService来说,如果想改变它的onStartComment()返回值,只需要调用setIntentRedelivery()。
Service
startService
startService:启动的服务与当前的activity没有关系,当前的activity结束后该服务仍旧可以单独存在。并且Service的生命周期会经过onCreate(),onStartCommand()再到onDestroy()。
如果调用startService()时服务已经创建,那么不会再次调用onCreate(),只会重复调用onStartCommand()。如果服务不存在,那么会首先调用onCreate(),再调用onStartCommand()。
采用startService()启动的服务,只能通过stopService()来停止,并且在停止时会调用onDestory()。此时并不能通过unbindService()进行停止,否则会报IllegalArgumentException异常。
bindService
启动的Service与当前的activity绑定在一起,activity退出时(调用onDestory()),Service也直接结束。此时service的生命周期为:onCreate(),onBind(),onUnbind(),onDestory()。
如果调用bindService()时服务已经存在,那么onBind()与onCreate()都不会被再次调用;如果服务不存在,就会依次调用onCreate()与onBind()。
通过bindService()启动的服务可以通过unbindService()结束,此时会依次执行onUnbindService()与onDestory()。
也可以通过stopService()进行结束,此时不会调用onUnbindService(),会直接调用onDestory()。