交互式通信之Service
我们知道Service是Android提供的一种后台运行机制的服务,主要运行在程序的后台,来完成不需要在前台显示的工作,比较常用,比如:后台的相关计算工作或是在后台运行监听程序等。那么这个后台组件是通过什么方式启动的那?
Service的启动方式分为两种(目前),分别为startService和bindService两种。启动的控制对象一般主要是通过Activity或者是Context(比如View等)来启动的。这两种启动方式所对应的Service的生命周期是不同的。下面即为Service的两种启动方式及不同的生命周期。如未说明一般是结合固有的属性方法来进行说明,这样更加易于理解和使用。具体可以参看下面的图形说明:
下面我以实际的例子来印证Service的两种启动方式的区别,这个例子就是在两种启动方式的Service中我们都使用线程来打印LOG日志,并通过是否打LOG来说明Service的生命周期是否结束(这只是为了说明),下面就来分析这两种启动方式下的Service的生命周期的区别。
startService启动方式:
在该启动方式下,Service的生命周期是这样的:当我们使用startService启动了Service之后,其生命周期:onCreate()->onStartCommand()->onStart(),当我们调用Service自身的stopSelf()或是stopService()的时候,其就会调用onDestroy()结束掉当前的Service,具体如下图:
如上图,当我们通过startService开启Service的时候,线程doTest一直打印LOG(红色部分1、2、3...),只有当我们调用stopService或是stopSelf的时候,Service停止运行并销毁(绿色部分),这就充分的说明了Service的声明周期。下面即为另一个问题,如果没有调用stopService或stopSelf,而是将启动该Service的Context关闭finish掉那?答案是该Service继续运行,如下图所示:
从上图可以看到,即时关掉了启动该Service的Context了,该服务还是继续运行,这就说明该服务Service并未与启动它的Context进行强关联(这与bindService正好相反)。下面列出以startService方式启动的源代码供参考:
public class MyStartService extends Service{
private static String TAG = "MyStartService";
private static boolean flag = false;
public static void runService(Context context) {
flag = true;
Intent intent = new Intent(context,MyStartService.class);
context.startService(intent);
}
@Override
public IBinder onBind(Intent intent) {
log("start_service_onbind");
return null;
}
@Override
public void onCreate() {
log("start_service_onCreate");
super.onCreate();
}
@Override
@Deprecated
public void onStart(Intent intent, int startId) {
log("start_service_onstart");
super.onStart(intent, startId);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
log("start_service_onstartcommand");
doTest();
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
log("start_service_ondestroy");
flag = false;
super.onDestroy();
}
@Override
public boolean onUnbind(Intent intent) {
log("start_service_onunbind");
return super.onUnbind(intent);
}
@Override
public void onRebind(Intent intent) {
log("start_service_onrebind");
super.onRebind(intent);
}
public static void stopService(Context context) {
Intent intent = new Intent(context,MyStartService.class);
context.stopService(intent);
}
private void log(String log) {
Log.d(TAG,log);
}
private void doTest() {
new Thread() {
public void run() {
int mills = 0;
while(flag) {
try {
Thread.sleep(1000);
mills ++;
log(""+mills);
}catch(Exception e) {
e.printStackTrace();
}
}
}
}.start();
}
}
bindService启动方式:
在该启动方式下,Service的生命周期是这样的:当我们使用bindService开启服务的时候,是这样的:onCreate()->onBind(),而当我们调用unBindService的时候,其调用顺序:onUnBind()->onDestroy()结束掉该服务,具体如下图:
从上面的图中,我们可以看出当使用bindService开启服务时,线程doTest一致打印LOG,当我们调用unBindService时,才会结束掉当前的服务Service。那么如果当我们将启动该服务的Context关闭掉那?结果就会与以startService方式完全相反了,这个Service也会马上随着这个Context的结束而停止,具体如下图:
在该种启动方式下,使用bindService启动的服务Service是与启动它的Context发生了强关联,如果当前的Context结束了,那么这个Service也会停止,该部分的源代码如下:
public class MyBindService extends Service {
private static String TAG = "MyBindService";
private static boolean flag = false;
private static IBinder binder = new Binder();
private static ServiceConnection connection = new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
binder = service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
binder = null;
}
};
public static void bindService(Context context) {
flag = true;
Intent intent = new Intent(context,MyBindService.class);
context.bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
@Override
public IBinder onBind(Intent intent) {
log("bind_service_onbind");
doTest();
return binder;
}
@Override
public void onCreate() {
log("bind_service_onCreate");
super.onCreate();
}
@Override
@Deprecated
public void onStart(Intent intent, int startId) {
log("bind_service_onstart");
super.onStart(intent, startId);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
log("bind_service_onstartcommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
log("bind_service_ondestroy");
flag = false;
super.onDestroy();
}
@Override
public boolean onUnbind(Intent intent) {
log("bind_service_onunbind");
return super.onUnbind(intent);
}
@Override
public void onRebind(Intent intent) {
log("bind_service_onrebind");
super.onRebind(intent);
}
public static void stopService(Context context) {
context.unbindService(connection);
}
private void log(String log) {
Log.d(TAG,log);
}
private void doTest() {
new Thread() {
public void run() {
int mills = 0;
while(flag) {
try {
Thread.sleep(1000);
mills ++;
log(""+mills);
}catch(Exception e) {
e.printStackTrace();
}
}
}
}.start();
}
}
而对于onRebind()方法则在service和旧的client之间的所有捆绑联系在onUnbind里面全都结束之后,如果有一个新的client用bind连接上service,就会启动onRebind()方法。
到这里,关于Service的两种启动方式下其生命周期就分析完了,当然在这里的bindService方式下的Service绑定涉及到了进程间通信机制IBinder,这个会在后面的AIDL部分去分析,在这里我们只需知道它是负责进程间通信的机制即可。
注意:上面的两个Service需要在AndroidManifest中注册(省略)。
/**
* 欢迎加入技术群:179914858
* 如果有任何问题请在评论中进行讨论学习
*/