IntentService与Service

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()。


你可能感兴趣的:(IntentService与Service)