二、清晰地理解Service

121 阅读4分钟

清晰地理解Service

问题1. Service的start和bind状态有什么区别?
  1. unbind只能解绑一次,否则会抛出异常,stopService可以一直Stop
  2. startService 每次调用都会触发onStartCommand ,只有第一次服务创建的时候触发onCreate,bindService,只触发一次onBind
  3. start启动的service,service有独立的生命周期,不依赖调用的组件,bind依赖调用的组件,调用 组件销毁后,服务也停止.
  4. intentSerivice 会自己调用stopSelf方法,内部使用的是HandlerThread
问题2. 同一个Service,先startService再bindService,如何把它停掉?

先startService再bindService,必须调用 unbindService和stopService 才能完全退出Service bindService 如果是不同的ServiceConnection,需要多次解绑,如果是相同的只需要解绑1次

问题3. 你有注意到Service的onStartCommand方法的返回值吗?不同的返回值有什么区别?
    /**
     * Constant to return from {@link #onStartCommand}: compatibility
     * version of {@link #START_STICKY} that does not guarantee that
     * {@link #onStartCommand} will be called again after being killed.
     *为了兼容版本,在Service被杀死后,并不保证onStartCommand会被再一次调用
     */
    public static final int START_STICKY_COMPATIBILITY = 0;
    
    /**
     * Constant to return from {@link #onStartCommand}: if this service's
     * process is killed while it is started (after returning from
     * {@link #onStartCommand}), then leave it in the started state but
     * don't retain this delivered intent.  Later the system will try to
     * re-create the service.  Because it is in the started state, it will
     * guarantee to call {@link #onStartCommand} after creating the new
     * service instance; if there are not any pending start commands to be
     * delivered to the service, it will be called with a null intent
     * object, so you must take care to check for this.
     * 
     *Service被杀死后,保留启动状态,但不保存intent,之后系统会重启service,并重新回
     *调onStartCommand方法,如果接下来没有其他start命令,intent会为null,所以需要
     *对Intent非空判断
     */
    public static final int START_STICKY = 1;
    
    /**
     * Constant to return from {@link #onStartCommand}: if this service's
     * process is killed while it is started (after returning from
     * {@link #onStartCommand}), and there are no new start intents to
     * deliver to it, then take the service out of the started state and
     * don't recreate until a future explicit call to
     * {@link Context#startService Context.startService(Intent)}.  The
     * service will not receive a {@link #onStartCommand(Intent, int, int)}
     * call with a null Intent because it will not be re-started if there
     * are no pending Intents to deliver.
     * 
     * 常规操作,除非死之前还有组件调用StartService,否则系统不会保留启动状态并重
     *启该Service
     */
    public static final int START_NOT_STICKY = 2;

    /**
     * Constant to return from {@link #onStartCommand}: if this service's
     * process is killed while it is started (after returning from
     * {@link #onStartCommand}), then it will be scheduled for a restart
     * and the last delivered Intent re-delivered to it again via
     * {@link #onStartCommand}.  This Intent will remain scheduled for
     * redelivery until the service calls {@link #stopSelf(int)} with the
     * start ID provided to {@link #onStartCommand}.  The
     * service will not receive a {@link #onStartCommand(Intent, int, int)}
     * call with a null Intent because it will will only be re-started if
     * it is not finished processing all Intents sent to it (and any such
     * pending events will be delivered at the point of restart).
     *
     *Serivce被杀死后,系统会组织一次service重启(除非这之前调用了stopSelf()方法),
     *被杀死前最后一次的传递Intent会重新执行,此falg保证了不会传递空Intent
     */
    public static final int START_REDELIVER_INTENT = 3;
问题4. Service的生命周期方法onCreate,onStart,onBind等运行在哪个线程?

Service运行在主线程中,Service中进行耗时操作也会出现ANR(IntentService 内部实现是通过新建HandlerThread线程,然后把任务放到子线程里面去运行,可以认为是Service里面又新建了子线程 )

问题5. 扩充问题 Service与Thread 有什么关系?

Service和Thread之间没有任何关系,Service的后台概念是指可以脱离UI运行,即使Activity被销毁,或者程序被关闭,只要进程还在,Service就可以继续运行.Service是运行在主线程中的,也会引起ANR.

当Activity被销毁之后,就没有任何其它的办法可以再重新获取到之前创建的子线程的实例。而且在一个Activity中创建的子线程,另一个Activity无法对其进行操作。但是Service就不同了,所有的Activity都可以与Service进行关联,然后可以很方便地操作其中的方法,即使Activity被销毁了,之后只要重新与Service建立关联,就又能够获取到原有的Service中Binder的实例。因此,使用Service来处理后台任务,Activity就可以放心地finish,完全不需要担心无法对后台任务进行控制的情况。