共计 4659 个字符,预计需要花费 12 分钟才能阅读完成。
前言
Service 算是四大组件中比较常用的吧,至少比起 Broadcase receiver 跟 Content provider 还算是用的多的,这里用来记录一些关于 Service 的小细节。
<!–more–>
startService 跟 bindService 所导致的生命周期
定义一个 Service 跟一个 Activity,分别如下:
public class MainActivity extends AppCompatActivity {
private Intent mIntent;
private MyServiceConnection mMyServiceConnection;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMyServiceConnection = new MyServiceConnection();
mIntent = new Intent(this, MyService.class);
}
public void startService(View view) {
startService(mIntent);
}
public void unbindService(View view) {
unbindService(mMyServiceConnection);
}
public void bingService(View view) {
bindService(mIntent, mMyServiceConnection, BIND_AUTO_CREATE);
}
public void stopService(View view) {
stopService(mIntent);
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.e(“jiang”, “onDestroy”);
}
class MyServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e(“jiang”, “onServiceConnected:”);
MyService.MyBinder myBinder = (MyService.MyBinder) service;
myBinder.systemOut();
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.e(“jiang”, “onServiceDisconnected:”);
}
}
}
public class MyService extends Service {
@Override
public void onCreate() {
super.onCreate();
Log.e(“jiang”, “onCreate”);
}
@Override
public IBinder onBind(Intent intent) {
Log.e(“jiang”, “onBind”);
return new MyBinder();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(“jiang”, “onStartCommand: flags :” + flags + ” startId :” + startId);
return super.onStartCommand(intent, flags, startId);
}
@Override
public void unbindService(ServiceConnection conn) {
super.unbindService(conn);
Log.e(“jiang”, “unbindService”);
}
@Override
public boolean onUnbind(Intent intent) {
Log.e(“jiang”, “onUnbind”);
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
Log.e(“jiang”, “onDestroy”);
super.onDestroy();
}
class MyBinder extends Binder {
public void systemOut() {
Log.e(“jiang”, “ 该方法在 MyService 的内部类 MyBinder 中 ”);
}
}
}
(1)、startService 所走的生命周期:
onCreate
onStartCommand: flags :0 startId :1
(2)、stopService 所走的生命周期:
onDestroy
(1)、bindService 所走的生命周期:
onCreate
onBind
onServiceConnected:
该方法在 MyService 的内部类 MyBinder 中
(2)、unDindService 所走的生命周期:
onUnbind
onDestroy
(1)、startService 所走的生命周期:
onCreate
onStartCommand: flags :0 startId :1
(2)、bindService 所走的生命周期:
onBind
onServiceConnected:
该方法在 MyService 的内部类 MyBinder 中
(3)、stopService 所走的生命周期:
什么也不走
(4)、unBindService 所走的生命周期:
onUnbind
(1)、startService 所走的生命周期:
onCreate
onStartCommand: flags :0 startId :1
(2)、bindService 所走的生命周期:
onBind
onServiceConnected:
该方法在 MyService 的内部类 MyBinder 中
(3)、unBindService 所走的生命周期:
onUnbind
(4)、stopService 所走的生命周期:
onDestroy
(1)、bindService 所走的生命周期:
onCreate
onBind
onServiceConnected:
该方法在 MyService 的内部类 MyBinder 中
(2)、startService 所走的生命周期:
onStartCommand: flags :0 startId :1
(3)、stopService 所走的生命周期:
什么也不走
(4)、unBindService 所走的生命周期:**
onUnbind
onDestroy
(1)、bindService 所走的生命周期:
onCreate
onBind
onServiceConnected:
该方法在 MyService 的内部类 MyBinder 中
(2)、startService 所走的生命周期:
onStartCommand: flags :0 startId :1
(3)、unBindService 所走的生命周期:
onUnbind
(4)、stopService 所走的生命周期:
onDestroy
如果 Service 被多次 start,会多次调用 onStartCommand,并会给 onStartCommand 参数 startId 传递调用的次数。
多次调用 unbindService 会报 java.lang.IllegalArgumentException: Service not registered: 异常,但是多次 bindService 就没有任何问题。
如果我们采用的是 startService 开启一个 Service,在 Activity 关闭后,Service 依旧运行在系统中。
如果我们采用的是 bindService 开启一个 Service,在 Activity 关闭时也会销毁 Service,就算你没有调用 unBindService 方法。
如果我们 start 并且 bind 一个 Service,怎么样才可以销毁这个 Service 呢?有以下几种方法:
调用 stopService 和 unbindService 这两个方法,调用顺序不分先后。
先调用 stopService,然后再关闭 Activity。
Service 的 onStartCommand 方法的返回值
一般来说,我们重写 Service 的 onStartCommand 方法都会返回 super.onStartCommand(intent, flags, startId),但这个默认的返回值是啥呢?我们一起到 Service 的源码中看看:
public @StartResult int onStartCommand(Intent intent, @StartArgFlags int flags, int startId) {
onStart(intent, startId);
return mStartCompatibility ? START_STICKY_COMPATIBILITY : START_STICKY;
}
通过 mStartCompatibility 进行三元运算法,从而返回不同的值,mStartCompatibility 其实表示的就是应用的 targetSdkVersion 是否小于 5。对于现在的 APP 来说,targetSdkVersion 早就大于 5 了,所以 mStartCompatibility 自然就为 false,而 super.onStartCommand(intent, flags, startId) 返回的就是 START_STICKY。
那么这个返回值又有什么用呢?说实话,我写代码来验证这个返回值貌似并不好使,也就是说不像注释说的那样牛逼,有时候会失效,甚至可以说是大部分都在失效。我们这里就来解读一下注释上所描述的返回值的作用:
START_STICKY_COMPATIBILITY:与 START_STICKY 效果相同,主要是为了兼容低版本,但是并不能保证每次都重启成功。
START_STICKY:进程被杀死以后,服务会自动重启,并调用 onStartCommand 方法,但是并不会保存 intent,所以需要在 onStartCommand 处理 intent 的话,记得要判空。但是 startId 会 +1。
START_NOT_STICKY:进程被杀死以后,服务并不会自动重启,就算是重新启动 App 也会不重启服务。
START_REDELIVER_INTENT:进程被杀死以后,服务会被自动重启,onStartCommand 方法会被调用,但是 intent 不为空,因为系统保存了上一次服务被杀死时的 intent 跟 startId。
对 onStartCommand 方法返回不同的返回值导致服务被杀死的时候自动重启,这个重启次数只能是一次。比如说服务被杀死一次以后,因为 onStartCommand 方法的返回值重启了这个服务,但是又被杀死了,这个时候服务不会再次因为 onStartCommand 方法的返回值重启服务了。
短时间的服务被多次杀死以后,系统就不愿意为你再重启这个服务了。
感谢
Android Service.onStartCommand() 方法 Service: onStartCommand 诡异的返回值 Android 中 Service 类中 onStartCommand 返回值介绍