Android之Service使用详解

版权声明:未经本人允许,严禁转载 https://blog.csdn.net/lmh_19941113/article/details/85549955

 本篇文章主要是讲解一些关于Service的知识点。

Service的生命周期

 Service有两种启动方式,startServicebindService
 首先来看startService,通过该方式启动的Service与调用者没有任何关联,调用者也无法调用该Service中的任何方法。生命周期如下:

 当第一次启动Service时会调用该Service的onCreate方法,然后调用onStartcommand,但当后面再次启动该Service且该Service还在运行中时,就会跳过onCreate方法,直接执行onStartCommand方法。
 Service还可以通过bindService来绑定Service。调用者绑定Service后,可以与该Service进行交互,但当调用者被销毁时也需要调用unBindService来解绑,所以绑定可以理解为不同生但同死。生命周期如下:

 只有当Service没有运行时才会调用onCreateonBind这两个方法,如果Service正在运行的话,这两个方法均不会执行。
 上面就是关于Service启动与Service绑定的生命周期介绍,其实一个Service可以同时调用startServicebindService。如果这样调用的话,结束的时候就必须同时停止和解绑Service。
 关于Service生命周期的具体调用可以阅读Android源码之Service启动流程这篇文章。

Service类onStartCommand()返回值

 通过startService启动Service时会调用onStartCommand这个方法,该方法有四种返回值,如下:

  • START_STICKY:如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。
  • START_NOT_STICKY:使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务。
  • START_REDELIVER_INTENT:使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入,重启服务并不是立即执行的,被异常kill次数越多,重启花费时间越长。
  • START_STICKY_COMPATIBILITYSTART_STICKY的兼容版本,但不保证服务被kill后一定能重启,但重启后不会调用onStartCommand这个方法。

 系统默认返回值是START_STICKYSTART_STICKY_COMPATIBILITY,所以使用Service时要注意onStartCommand的返回值,避免异常kill掉导致程序崩溃。
 关于Service的自启动流程可以阅读Android之Service自启动流程这篇文章

IntentService的使用

 一般Service都是运行在主线程的,也就意味着无法再Service中做耗时操作,除非在Service中开启子线程,但这样的话就稍微麻烦一点了。于是谷歌就倒腾了IntentService这个类,在IntentService中能很方便的进行一些耗时操作且不用开发者自己管理Service和线程。下面就来看一下IntentService的实现:

public abstract class IntentService extends Service {
    private volatile Looper mServiceLooper;
    private volatile ServiceHandler mServiceHandler;
    private String mName;
    private boolean mRedelivery;

    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            //执行耗时操作,如果执行完毕后没有新的Intent传递进来就会销毁当前Service
            onHandleIntent((Intent)msg.obj);
            //销毁当前Service
            stopSelf(msg.arg1);
        }
    }

    public IntentService(String name) {
        super();
        mName = name;
    }
    public void setIntentRedelivery(boolean enabled) {
        mRedelivery = enabled;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        //创建一个HandlerThread,HandlerThread是Handler+Thread的实现
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        //开启子线程
        thread.start();
        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

    @Override
    public void onStart(@Nullable Intent intent, int startId) {
        //发生一条消息
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }
    @Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        //结束线程
        mServiceLooper.quit();
    }
    @Override
    @Nullable
    public IBinder onBind(Intent intent) {
        return null;
    }
    //需要子类实现的方法,在该方法内可以执行耗时操作
    @WorkerThread
    protected abstract void onHandleIntent(@Nullable Intent intent);
}

 上面就是HandlerService的实现了,还是比较简单的,我们只管做自己的操作即可,Service及线程由IntentService自己管理。

【参考资料】
【移动开发】Service类onStartCommand()返回值和参数
startService与bindService的区别

猜你喜欢

转载自blog.csdn.net/lmh_19941113/article/details/85549955
今日推荐