各位肯定知道 Service 作为 Android 的四大组件之一是非常重要的。不过说实话,我实际开发项目中服务用的并不多,(可能和需求有关吧)但是笔试的时候,几乎是必出的题目了,所以我们今天就来仔细的回顾一下 Service 。
1. 什么是服务?
Service 是表示应用程序需求的应用程序组件,在不与用户交互的情况下执行长时间运行的操作,或者给其他应用程序提供使用的功能。Service 是和应用程序在同一个进程中运行的,Service 并不是一个线程,所以它并不是用来处理耗时操作的。
2. 启动服务的方式有几种?(启动服务需要在 AndroidManifest.xml 文件配置)
3. Service 的方法和常量有哪些?
Return | Methode |
final Application | getApplication() 返回拥有此服务的Application。 |
adstract IBinder | onBind(Intent intent) 将通信通道返回给服务。 |
void | onConfigurationChanged(Configuration newConfig) 当组件运行时,设备配置发生变化时由系统调用。 |
void | onCreate() 首次创建服务时由系统调用。 |
void | onDestroy() 由系统调用以通知服务它已不再使用且正在被删除。 |
void | onLowMemory() 当整个系统内存不足时调用此方法,并且主动运行的进程应调整其内存使用量。 |
void | onRebind() 当新客户端连接到服务时调用,在此之前,它已经被通知所有客户端在其onUnbind(Intent)中断开连接。 |
void | onStart(Intent intent,int startId) 此方法在API级别5中已弃用。请实现onStartCommand(Intent,int,int)。 |
int | onStartCommand(Intent intent,int flags,int startId) 每次客户端通过调用Context.startService(Intent)显式启动服务时,由系统调用,提供它提供的参数和表示启动请求的唯一整数标记。 |
void | onTaskRemoved(Intent rootIntent) 如果服务当前正在运行,且用户删除了来自服务应用程序的任务,则调用此函数。 |
void | onTrimMemory(int level) 当操作系统确定是进程从进程中删除不需要的内存的好时机时调用。 |
boolean | onUnbind(Intent intent) 当所有客户端与服务发布的特定接口断开连接时调用。 |
final void | startForeground(int flags) 将此服务从前台状态删除,允许在需要更多内存时终止该服务。 |
final void | startForeground(boolean removeNotification) 同 startForeground(int flags) |
final void | startForeground(int id,Notification notification) 如果您的服务已启动(通过Context.startService(Intent)运行),则还要使此服务在前台运行,从而提供在此状态下向用户显示的持续通知。 |
final void | stopSelf() 停止服务,如果服务之前已经启动。 |
final void | stopSelf(int startId) 不再返回结果的旧版本的stopSelfResult(int)。 |
final boolean | stopSelfResult(int startId) 如果最近一次启动的是startId,则停止服务。 |
Constants | |
int | START_CONTINUATION_MASK onStartCommand返回的位(Intent, int, int)描述了如果服务被终止,如何继续服务。 |
int | START_FLAG_REDELIVERY 如果Intent是先前传递的intent的重新传递,则此标志在onStartCommand(Intent,int,int)中设置,因为该服务先前已返回START_REDELIVER_INTENT但在为该Intent调用stopSelf(int)之前已被杀死。 |
int | START_FLAG_RETRY 如果意图是重试,则在onStartCommand(Intent, int, int)中设置此标志,因为初始尝试从未到达或从onStartCommand(Intent, int, int)返回。 |
int | START_NOT_STICKY 从onStartCommand(Intent,int,int)返回的常量:如果此服务的进程在启动时被终止(从onStartCommand(Intent,int,int)返回后),并且没有新的启动意图要传递给它,那么 将服务从启动状态中取出,并且在将来显式调用Context.startService(Intent)之前不要重新创建。 |
int | START_REDELIVER_INTENT 从onStartCommand(Intent,int,int)返回的常量:如果此服务的进程在启动时被终止(从onStartCommand(Intent,int,int)返回后),则它将被安排重新启动并且最后一次传递的Intent 通过onStartCommand(Intent,int,int)再次传递给它。 |
int | START_STICKY 从onStartCommand(Intent,int,int)返回的常量:如果此服务的进程在启动时被终止(从onStartCommand(Intent,int,int)返回后),则将其保留在启动状态但不保留此状态 交付 intent。 |
int | START_STICKY_COMPATIBILITY 从onStartCommand(Intent,int,int)返回的常量:START_STICKY的兼容版本,不保证在被杀死后再次调用onStartCommand(Intent,int,int)。 |
int | STOP_FOREGROUND_DETACH stopForeground(int)的标志:如果设置,则先前提供给startForeground(int,Notification)的通知将与服务分离。 |
int | STOP_FOREGROUND_REMOVE stopForeground(int)的标志:如果设置,将删除先前提供给startForeground(int,Notification)的通知。 |
4. 服务的生命周期
(1)Context.startService() 的生命周期。(和开启者的生命周期无关,如果不显示的停止 Service,Service 会一直运行。)
首次启动 Service 会先调用 onCreate() ,然后调用 onStartCommand(),至此 Service 任务就启动了。我们再次启动相同 Service,你会发现只调用了 onStartCommand(),也就是说 onCreate() 只会被调用一次,onStartCommand()会调用多次。当我们停止 Service 会调用 onDestroy(),至此 Service 就停止了。生命周期结束!
public class MyService extends Service {
public static final String TAG = "My_Service";
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "MyService --> onCreate");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "MyService --> onStartCommand");
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "MyService --> onDestroy");
}
}
Intent intent = new Intent(ServiceActivity.this, MyService.class);
startService(intent);
stopService(intent);
D/My_Service: MyService --> onCreate
D/My_Service: MyService --> onStartCommand
D/My_Service: MyService --> onStartCommand
D/My_Service: MyService --> onDestroy
(2)Context.bindService() 的生命周期。(和开启者的生命周期绑定,随着开启者的销毁而销毁)
首次启动 Service 会调用 onCreate() ,同样的也是只会调用一次。随后会调用 onBind() 。销毁 Service 会调用先调用onUnbind(),随后会调用 onDestroy()。至此生命周期结束!
public class MyService extends Service {
public static final String TAG = "My_Service";
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG,"MyService --> onBind");
return new MyBinder();
}
@Override
public boolean onUnbind(Intent intent) {
Log.d(TAG,"MyService --> onUnbind");
return super.onUnbind(intent);
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "MyService --> onCreate");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "MyService --> onStartCommand");
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "MyService --> onDestroy");
}
public class MyBinder extends Binder implements IPersonalInif{
@Override
public String getName() {
return "Test Name";
}
}
public interface IPersonalInif {
String getName();
}
}
public class MyServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mInfoService = (MyService.IPersonalInif) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onBindingDied(ComponentName name) {
}
}
Intent intent = new Intent(ServiceActivity.this, MyService.class);
mMyServiceConnection = new MyServiceConnection();
bindService(intent, mMyServiceConnection, Service.BIND_AUTO_CREATE);
Log.d(TAG,"IPersonalInif --> name --> " + mInfoService.getName());
unbindService(mMyServiceConnection);
D/My_Service: MyService --> onCreate
D/My_Service: MyService --> onBind
logcat 没有任何输出,也就是再次启动没有任何回调!
D/Service_Activity: IPersonalInif --> name --> Test Name
D/My_Service: MyService --> onUnbind
D/My_Service: MyService --> onDestroy
(3)先 Context.startService() 在 Context.bindService() 的生命周期。(这种方式的代码就不贴了,说说场景,和流程吧)
如果 Service 由某个客户端通过 Context.startService() 启动,接下来由其他客户端通过 Context.bindService() 绑定到该 Service,然后在调用 unbindService() 解除该 Service,然后在通过 Context.bindService() 绑定到该 Service,那么生命周期的步骤如下:
onCreate() --> onStartCommand --> onBind() --> onUnbind() --> onRebind()
注意:前提是 onUnbind() 返回 true,读到这里可能会有点疑惑,那就是我明明调用了 unbindService() 方法,系统为什么不调用 Service 的 onDestroy() 呢?这是因为 Service 是我们先 Context.startService() 启动的,所以系统只会调用 onUnbind(),不会调用 onDestroy()。(我们使用 Context.bindService() 绑定一个已经启动的 Service ,系统只是会将 Service 内部的 IBinder 对象传递给 Activity,并不会将 Service 的生命周期和 Activity 的生命周期绑定,所以我们即使调用 unbindService(),也是不会销毁 Service的)
至此,Service 的使用以及生命周期已经讲解完了,希望对你有帮助!
欢迎加入Q群一起探讨Android问题。