简介
Android Service的生命周期比activity要简单,很多android开发同学,都可以脱口而出,但service生命周期又很混乱,因为其生命周期并不是一成不变的。所以又有时我们会傻傻分不清楚。所以我们在这里用几个例子把service的生命周期彻底搞清楚。
目录
Service的生命周期
service的生命周期有哪些呢?
- onCreate : 当Service被创建时执行
- onStartCommand:当执行startService时被调用
- onStart:已经被onStartCommand代替,在本文中,将不在讨论onStart。
- onBind:当执行bindService时被调用。
- onUnbind:当执行unbindService是被调用
onDestroy:当Service被销毁时被调用
这几个生命周期大家应该都清楚,但我们很难像Activity一样把这些生命周期串在一起。因为在不同的情况下。生命周期的会有不同的组合方式,下面我们举个栗子来分析一下。
举个栗子
栗子来了,首先我们有一个这样的MainActivity
Activity中有四个Button 分别是
1. startService 启动service
2. bindService 绑定service
3. stopService 停止service
4. unbindService 解绑service
MainActivity的代码如下:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = MainActivity.class.getSimpleName();
private ServiceConnection serviceConnection;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
serviceConnection = new MainServiceConnection();
findViewById(R.id.btn_start_service).setOnClickListener(this);
findViewById(R.id.btn_bind_service).setOnClickListener(this);
findViewById(R.id.btn_stop_service).setOnClickListener(this);
findViewById(R.id.btn_unbind_service).setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_start_service:
Intent startIntent = new Intent(this, MainService.class);
startService(startIntent);
break;
case R.id.btn_bind_service:
Intent bindIntent = new Intent(this, MainService.class);
bindService(bindIntent, serviceConnection, BIND_AUTO_CREATE);
break;
case R.id.btn_stop_service:
Intent stopIntent = new Intent(this, MainService.class);
stopService(stopIntent);
break;
case R.id.btn_unbind_service:
unbindService(serviceConnection);
break;
}
}
private class MainServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d("testService", TAG + " onServiceConnected()");
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d("testService", TAG + " onServiceDisconnected()");
}
}
}
代码很简单,我们分别为四个Button设置了四个点击事件,分别是:
- startService(startIntent);
- bindService(bindIntent, serviceConnection, BIND_AUTO_CREATE);
- stopService(stopIntent);
- unbindService(serviceConnection);
还有MainService的代码如下:
public class MainService extends Service {
private static final String TAG = MainService.class.getSimpleName();
private MyBinder myBinder = new MyBinder();
@Override
public void onCreate() {
super.onCreate();
Log.d("testService", TAG + " onCreate()");
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.d("testService", TAG + " onBind()");
return myBinder;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("testService", TAG + " onStartCommand()");
return super.onStartCommand(intent, flags, startId);
}
@Override
public boolean onUnbind(Intent intent) {
Log.d("testService", TAG + " onUnbind()");
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
Log.d("testService", TAG + " onDestroy()");
super.onDestroy();
}
public class MyBinder extends Binder {
public MainService getService() {
return MainService.this;
}
}
}
MainService就是被MainActivity启动的service,在这个类里我们将Service的主要生命周期打印了出来。下面问题来了
问题一 启动service的生命周期是怎样的呢
我们知道启动一个Service有两种方法分别是startService 和 bindService 那么我们提出一个问题。当我们分别执行以下四种情况,生命周期会是怎样的呢。
我们分别点击:
怎么样,心理有答案了么?
情况一 :点击两次startService
log输出如下所示:
再画个图来示意一下:
service首次启动时会先回调onCreate,然后回调onStartCommand。当第二次启动Service时,因为这时Service已经被Create过,所以只回调onStartComment。同样,当第三次执行onStart时依然只会回调onStartComment。
情况二:点击startService——>bindService
log输出如下所示:
生命周期示意图如下:
跟之前一样,在执行startService时,会回调onCreate和onStartCommand,而当执行bindService时会回调onBind函数。
情况三:点击两次bindService
log输出如下所示:
生命周期示意图如下:
首次点击bindService时会执行onCreateService(我们在bindService时使用了参数BIND_AUTO_CREATE
如字面意思,在绑定service时会自动创建service)和onbind,但是再次执行bindservice,我们发现没有任何效果的。
bindService是将MainActivity和MianService绑定到一起,但当两个对象已经绑定之后,重复绑定也就没有任何意义了。
情况四:点击bindService——>startService
log输出如下所示:
生命周期示意图如下:
执行bindService后,会回调onCreate 和 onbind,再执行startService后会回调onStartCommend。
问题二 结束service的生命周期又是怎样的呢
结束service可以通过unbindService和StopService来实现。在不同的情况下,执行这两条命令,会得到不同的生命周期,接下来我们不在截图日志输出了,直接用框图来一一列举不同的生命周期。
stopService
情况一:
我们执行startService后执行stopService会回调onDestroy函数
情况二:
我们执行bindService后执行stopService会发现没有反应
情况三:
当我们执行startService和bindService后执行stopService发觉没有反应
unbindService
情况一:
我们执行bindService后执行unbindService会回调onUnbind和onDestroy
情况二:
当我们执行startService后执行unbindService发现崩溃了。。。。。
情况三:
当我们执行startService和bindService后执行unbindService,只会回调onUnbind
特殊情况
情况一:
当执行startService和bindService后执行unbindService会回调onBind函数,在调用stopService后会回调onDestroy函数。
情况二:
当执行startService和bindService后执行stopService看似没反应,这里之所以说看似没反应,是因为,他实际导致生命周期的变化。原本点击onUnbindService后只会回调onUnbind但这是同时回调了onDestroy函数。这里我们可以得出结论,在执行stopService时并非真的没有效果,程序只是将执行情况记录下来,并在执行onUnbindService时体现了出来。
问题三 ServiceConnection
private class MainServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d("testService", TAG + " onServiceConnected()");
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d("testService", TAG + " onServiceDisconnected()");
}
}
在bindService时,我们都需要传入一个实现了接口ServiceConnection的对象,里面有两个监听函数。这里需要说明一下
1、当bindService成功是会回调onServiceConnected
2、当unbindService成功之后 不会、不会、不会!!!执行onServiceDisconnected,是不是很坑,这里只有当service意外停止,导致disconnected时才会回调。
总结一下
上面说了那么多,是不是已经晕了,怎么记啊???不要着急,下面就来总结一下,只要记住以下结论,就不会用错了。
- 首次启动Service时会回调onCreate函数,并且在整个生命周期中只回调一次。
- 每次调用startService都会回调一次onStart函数。
- bindService只能绑定一次,再次绑定回无效。
- startService和stopService应该成对出现,即有startService就应该有stopService
- bindService和unbindService应该成对出现,及有bindService就应该有unbindeServcie。切忌,unbindService单独出现会崩溃
- onServiceDisconnected并不是在执行unbindService时回调的,是在Service意外停止时回调的。
好了Service的生命周期就介绍到这里了。有问题欢迎指正