一、Service生命周期(两种途径):
1>onCreate()--->onStartCommand()--->(onStart())--->onDestroy()
被开启的service通过其他组件调用 startService()被创建。
这种service可以无限地运行下去,必须调用stopSelf()方法或者其他组件调用stopService()方法来停止它。无论调用了多少次startService(),都 只需调用一次 stopService()来停止。
当service被停止时,系统会销毁它。
2>onCreate()--->onBind()--->onUnbind()--->onDestory()
被绑定的service是当其他组件(例如:TestActivity)调用bindService()来创建的。
TestActivity可以通过一个IBinder接口和service进行通信[下面会简单介绍和Activity之间传递数据]
TestActivity可以通过unbindService()方法来关闭这种连接。
一个service可以同时和多个Activity绑定,当多个Activity都解除绑定之后,系统会销毁service。
注意:onStartComand使用时,返回的是一个(int)整型。有四个返回值类型: START_STICKY、START_NO_STICKY、START_REDELIVER_INTENT、START_STICKY_COMPATIBILITY
1>START_STICKY: 如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由 于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传 递到service,那么参数Intent将为null。
2>START_NOT_STICKY:“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务
3>START_REDELIVER_INTENT:重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。
4>START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保证服务被kill后一定能重启。
当然这两种方式并不是完全分开的,你还可以将一个已经strartService的服务进行绑定,例如:一个后台播放器服务通过startService被启动来播放音乐,可能在播放过程中用户要执行一些操作或者获取一些歌曲信息,此时可以通过bingService与Service建立连接,这种情况下,stopService()或 stopSelf()实际上并不能停止这个service,直到最后一次绑定关闭
二、IntentService
服务中的代码都是默认都是运行在主线程当中 ,如果直接在服务里去处理一些耗时的逻辑,就很容易出现ANR ( Application Not Responding ) 的情况。
所以这个时候就需要用到Android多线程编程的技术了,我们应该在服务的每个具体的方法 里开启一个子线程,然后在这里去处理那些耗时的逻辑。因此,一个比较标准的服务就可以写成 如下形式:
public class MyService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startld) {
new Thread(new Runnable() {
@Override
public void run() {
//处理具体的逻辑操作
}
}).start();
return super.onStartCommand(intent, flags, startld);
}
}
但是,服务一旦启动就会一直运行,必须调用stopSelf或者stopService才会停止,所以要想让一个服务执行完逻辑操作之后自动关闭,就需要调用stopSelf(); 如下:
public class MyService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startld) {
new Thread(new Runnable() {
@Override
public void run() {
//处理具体的逻辑
stopSelf();
}
}).start();
return super.onStartCommand(intent, flags, startld);
}
}
因此,为了避免忘记开启线程或者手动关闭服务,Android专门提供了IntentService:
public class MyService extends IntentService{
//必须要有此构造方法,在其内部调用父类的有参构造函数
public MyService() {
super("MyService");
}
//该方法在子线程中运行,不用再手动开辟线程
@Override
protected void onHandleIntent(@Nullable Intent intent) {
}
//服务执行完会自动调用该方法停止,不用在手动关闭服务
@Override
public void onDestroy() {
super.onDestroy();
}
}
IntentService集开启线程和自动停止于一身,得到了不少程序员的喜爱。
三、Android中Service与Activity数据交互:
1>通过startService()与stopService()启动和停止服务,Service与启动它的Activity无法进行通信和数据交换
2>通过bindService(Intent, ServiceConnection, int)与unbindService(ServiceConnection)启动和停止服务
注意:类ServiceConnection中的onServiceDisconnected()方法在正常情况下是不会被调用的,它的调用时机是当 Service服务被异外销毁时,例如内存的资源不足时. 另外,多个客户端可以绑定同一个服务,如果Service还未被启动,bindService()方法可以启动服务。
要进行数据交互:
首先创建一个Service中,并在创建Service类时,创建一个bind对象,在onBind方法中返回
private TempService.MyBinder binder;
public class TempService extends Service{
private MyBinder myBinder=new MyBinder();
public class MyBinder extends Binder{
//这里可以返回给Activity交互的数据
public String getTemp(){
return "返回值";
}
}
@Override
public IBinder onBind(Intent intent) {
return myBinder;
}
}
在Activity中绑定获取数据
private ServiceConnection connection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 这里的参数service就是交互的数据
binder=(TempService.MyBinder) service;
ToastUtil.tostshort(LoginActivity.this,binder.getTemp());
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
附:
1.Service的start和bind的区别?
start启动的Service,service有独立的生命周期,不依赖启动它的组件;
多次调用start方法,会重复调用onStartCommand方法;
start启动的Service,必须通过stopService或者stopSelf来停止service(IntentService会自动调用stopSelf方法【上面提到过】);
多次调用bind方法,只会调用一次onBind方法;
bind绑定的service,service依赖于这些组件,这些组件全部销毁后,service也会随之销毁
2.同一个Service,先startService然后再bindService,怎样把它停止掉?
无论startService被调用几次,只需stopService(或者stopSelf方法)一次就好;
调用多次bindService,必须调用多次unbindService方法;
因此,需要调用一次stopService(或者stopSelf方法)和多次unbindService方法,执行顺序没有要求,最后一个stopService或者unbindService方法会导致Service的onDestroy执行
3.service的onStartCommand方法的返回值,不同返回值有什么区别?
共有四种返回值:
START_STICKY:service被杀死后,保留启动状态,但不保存intent,之后系统会尝试重启service,并重新回调onStartCommand方法
START_NOT_STICKY:常规操作,除非service杀死之前还有组件调用startService,否则系统不会保留启动状态并重启该Service
START_STICKY_COMPATILITY:为了兼容版本,在service被杀死后,并不保证onStartCommand会被再一次调用
START_REDELIVER_INTENT:service被杀死后,系统将会组织一次service重启(除非在那之前调用stopSelf()方法),被杀死前最后一次传递的Intent将重新被执行,该flag将不会传递空intent
4.Service的生命周期方法onCreate、onStart、onBind等运行在哪个线程?
Service默认是运行在主线程的,其生命周期方法也是运行在主线程;因此如果要在Service中执行耗时操作,必须另开辟线程(或使用IntentService),否则可能会产生ANR。