浅析Android Service 中 onStartCommand方法及注意事项

1、Service 的生命周期

这里写图片描述
  以调用startService()为例,上图中onCreate方法仅在startSercice()调用后运行一次;然后运行onStartCommand(); onDestory ()仅在stopService()或stopSelf()方法调用后执行一次。
   那么在这期间,如果service被系统kill掉,那么会重新调用onStartCommand()来重新运行。

2、onStartCommand方法

onStartComand的返回值

   这个整形可以有四个返回值:start_sticky、start_no_sticky、START_REDELIVER_INTENT、START_STICKY_COMPATIBILITY。
它们的含义分别是:

  • START_STICKY: 如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由 于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传 递到service,那么参数Intent将为null;

  • START_NOT_STICKY:“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务;

  • START_REDELIVER_INTENT:重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入;

  • START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保证服务被kill后一定能重启。

onStartCommand参数flags含义

flags表示启动服务的方式:
Additional data about this start request. Currently either 0, START_FLAG_REDELIVERY, or START_FLAG_RETRY.

  • START_FLAG_REDELIVERY: 如果你实现onStartCommand()来安排异步工作或者在另一个线程中工作, 那么你可能需要使用START_FLAG_REDELIVERY来 让系统重新发送一个intent。这样如果你的服务在处理它的时候被Kill掉, Intent不会丢失.
  • START_FLAG_RETRY:表示服务之前被设为START_STICKY,则会被传入这个标记

3、使用注意事项

   由于onStartCommand会被重复调用,因此在onStartCommand中申请了资源或添加了Window,然后在onDestory中释放的逻辑是不成立的,因为系统异常kill掉service不会调用onDestory,而重复调用onStartCommand方法又会在上次资源或window没有释放的情况下重新申请,这样就会产生无法预估的错误。
  如下代码,我在onStartCommand中添加了Window,在onDestory中进行了释放,就遇到了Service启动后被异常kill掉的情况,结果就同时出现了多个窗口导致无法操作。因此需要在window添加处进行判空处理,保证服务可以重启,但window只能有一个。

 @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // TODO Auto-generated method stub
        if (mWindowManager == null) {
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    Log.d(TAG,
                            "BootLockSerivce,launchBootLockPasswordManagerFragment!");
                    mWindowManager = (WindowManager) getApplicationContext()
                            .getSystemService(WINDOW_SERVICE);
                    WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
                    layoutParams.type = (WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW
                            + 22);
                    layoutParams.height = WindowManager.LayoutParams.MATCH_PARENT;
                    layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
                    mView = View.inflate(getApplicationContext(),
                            R.layout.app_password_manager_layout, null);
                    mWindowManager.addView(mView, layoutParams);
                    findViewById(mView);
                    generateFormula();
                    setNumKeysListener();
                    monitorResultInput();
                }
                // }, 50);
                // 低端机需要延迟5s来规避聚好看
            }, 5000);
        }

扫描二维码关注公众号,回复: 997197 查看本文章

猜你喜欢

转载自blog.csdn.net/sdsxtianshi/article/details/80285666
今日推荐