Android面试——Service篇
注意:
onStart() 被标记为弃用,用 onStartCommand()代替;没有onStop()回调方法;
一:Service的两种启动方式,以及对应的生命周期
1. startService
onCreate() -> onStartCommand() -> onDestroy()
如果服务已经开启,多次执行startService不会重复的执行onCreate(), 而是会调用onStart() 和 onStartCommand()。
使用startService()方法启用服务,调用者与服务之间没有关连,即使调用者退出了,服 务仍然运行。
当执行stopService时,直接调用onDestroy方法
2. bindService
onCreate() -> onbind() -> onUnbind()-> onDestroy()
如果服务已经开启,多次执行bindService时,onCreate和onBind方法并不会被多次调用
调用者调用unbindService方法或者调用者Context不存在了(如Activity被finish了),Service就会调用onUnbind->onDestroy
使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止。
调用unbindService会执行onUnbind、onDestroy
二:Service的启动流程
与Activity的启动流程类似:
1. 进程A 通过Binder 向System_Server发起startService请求;
2. 如果生成的服务需要运行在独立的进程,则需要向Zygote进程发送创建进程的请求;Zygote进程fork纯新进程B
3. 服务的进程(A或者B)向Systemserver进程发起attachApplication请求;
4. Systemserver进程经过一系列处理后,向服务所在进程发起scheduleCreateService请求;
5. 服务所在进程收到请求后,通过handler向主线程发送CREATE_SERVICE消息
6. 主线程收到消息后,通过反射机制创建目标Service,并回调Service.onCreate()方法
三:Service与Activity如何实现通信
第一种方式:通过Binder对象
1. Service 添加一个继承Binder的内部类,并添加相应的逻辑方法;
2. Service 重写 onBind()方法,返回刚才定义的内部类的实例;
3. 在Activity中,绑定服务, 使用匿名内部类的方式创建ServiceConnection的对象,并且重写onServiceConnected方法,根据传入的IBinder,调用相应的逻辑方法
第二种方式:通过广播通信
注意:这里是列出实际的两种例子,实际上可以根据是进程间或是线程间通信来进行处理,非进程间无需使用binder;
四:IntentService 原理,应用场景,以及与Service的区别
1. 是什么
IntentService 是 Service的子类, 默认开启了一个工作线程HandlerThread,使用这个线程逐一处理所有启动请求,任务执行完毕会自动停止服务;
只要实现一个方法,onHandleIntent,该方法会接收每个启动请求的Intent,能够执行后台工作和耗时操作;
可以启动IntentService 多次,每个耗时操作会以队列的形式在IntentService 的 onHandlerIntent 方法中执行,每次执行一个工作线程,并且所有消息执行完才终止服务;
2. 怎么做
a. 创建一个名叫ServiceHandler的内部Handler
b. 把内部handler 与HandlerThread 所对应的子线程进行绑定
c. handlerThread 开启线程, 创建自己的Looper
d. 通过onstartCommand,一次插入到工作队列中,并发送给onHandleInten()逐个处理
3. 与Service的区别
一是 需要构造方法传入工作线程的名称
二是多了一个回调方法 onHandleIntent
三是 Service 主线程不能处理耗时操作,否则会ANR,IntentService则不会
四是 为Service的onBind()提供默认实现,返回null;onStartCommand提供默认实现,将请求Intent添加到队列中
五是 所有请求处理完成后,IntentService会自动停止,无需调用stopSelf()方法停止Service
五:Service的onStartCommand 方法返回值的含义?
START_NOT_STICKY:执行完 onStartCommand 后,服务被异常 kill 掉,系统不会自动重启该服务
START_STICKY:使用这个返回值时,如果在执行完 onStartCommand 后,服务被异 常 kill 掉,系统会自动重启该服务,并且onStartCommand方法会执行,onStartCommand方法中的intent值为null
START_REDELIVER_INTEN:使用这个返回值时,服务被异 常 kill 掉,系统会自动重启该服务,并将 Intent 的值传入;适用于主动执行应该立即恢复的作业(例如下载文件)的服务
六:bindService和startService混合使用的生命周期以及怎么关闭
1. 如果只想启动服务进行某项任务,使用startService即可
2. 如果相与Service保持练习,可以使用broadcast或者bindService
如果先startService,再bindService
onCreate() -> onStartCommand() -> onbind()
如果先bindService,再startService
onCreate() -> onbind() -> onStartCommand()
如果只stopService
Service的OnDestroy()方法不会立即执行,在Activity退出的时候,会执行OnDestroy。
如果只unbindService
只有onUnbind方法会执行,onDestory不会执行
如果要完全退出Service,那么就得执行unbindService()以及stopService。
注意:想实现Activity退出,Service依然存在,可以只unbindService,此时onDestory不会执行;