Android Service服务
参考:service初涉
service服务的生命周期示意图:
启动service的方法
1)StartService()启动Service
2)BindService()启动Service
PS:还有一种,就是启动Service后,绑定Service!
service的相关方法
onCreate():当Service第一次被创建后立即回调该方法,该方法在整个生命周期 中只会调用一次!
onDestory():当Service被关闭时会回调该方法,该方法只会回调一次!
onStartCommand(intent,flag,startId):早期版本是onStart(intent,startId), 当客户端调用startService(Intent)方法时会回调,可多次调用StartService方法, 但不会再创建新的Service对象,而是继续复用前面产生的Service对象,但会继续回调 onStartCommand()方法!
IBinder onOnbind(intent):该方法是Service都必须实现的方法,该方法会返回一个 IBinder对象,app通过该对象与Service组件进行通信!
onUnbind(intent):当该Service上绑定的所有客户端都断开时会回调该方法!
StartService启动Service
①首次启动会创建一个Service实例,依次调用onCreate()和onStartCommand()方法,此时Service 进入运行状态,如果再次调用StartService启动Service,将不会再创建新的Service对象, 系统会直接复用前面创建的Service对象,调用它的onStartCommand()方法!
②但这样的Service与它的调用者无必然的联系,就是说当调用者结束了自己的生命周期, 但是只要不调用stopService,那么Service还是会继续运行的!
③无论启动了多少次Service,只需调用一次StopService即可停掉Service
BindService启动Service
①当首次使用bindService绑定一个Service时,系统会实例化一个Service实例,并调用其onCreate()和onBind()方法,然后调用者就可以通过IBinder和Service进行交互了,此后如果再次使用bindService绑定Service,系统不会创建新的Sevice实例,也不会再调用onBind()方法,只会直接把IBinder对象传递给其他后来增加的客户端!
②如果我们解除与服务的绑定,只需调用unbindService(),此时onUnbind和onDestory方法将会被调用!这是一个客户端的情况,假如是多个客户端绑定同一个Service的话,情况如下 当一个客户完成和service之间的互动后,它调用 unbindService() 方法来解除绑定。当所有的客户端都和service解除绑定后,系统会销毁service。(除非service也被startService()方法开启)
③另外,和上面那张情况不同,bindService模式下的Service是与调用者相互关联的,可以理解为 “一条绳子上的蚂蚱”,要死一起死,在bindService后,一旦调用者销毁,那么Service也立即终止!
通过BindService调用Service时调用的Context的bindService的解析 bindService(Intent Service,ServiceConnection conn,int flags)
service:通过该intent指定要启动的Service
conn:ServiceConnection对象,用户监听访问者与Service间的连接情况, 连接成功回调该对象中的**onServiceConnected(ComponentName,IBinder)**方法; 如果Service所在的宿主由于异常终止或者其他原因终止,导致Service与访问者间断开 连接时调用onServiceDisconnected(CompanentName)方法,主动通过unBindService() 方法断开并不会调用上述方法!
flags:指定绑定时是否自动创建Service(如果Service还未创建), 参数可以是0(不自动创建),BIND_AUTO_CREATE(自动创建)
StartService启动Service后bindService绑定
如果Service已经由某个客户端通过StartService()启动,接下来由其他客户端 再调用bindService()绑定到该Service后调用unbindService()解除绑定最后在 调用bindService()绑定到Service的话,此时所触发的生命周期方法如下:
onCreate( )->onStartCommand( )->onBind( )->onUnbind( )->onRebind( )
PS:前提是:onUnbind()方法返回true!!! 这里或许部分读者有疑惑了,调用了unbindService后Service不是应该调用 onDistory()方法么!其实这是因为这个Service是由我们的StartService来启动的 ,所以你调用onUnbind()方法取消绑定,Service也是不会终止的!
得出的结论: 假如我们使用bindService来绑定一个启动的Service,注意是已经启动的Service!!! 系统只是将Service的内部IBinder对象传递给Activity,并不会将Service的生命周期 与Activity绑定,因此调用unBindService( )方法取消绑定时,Service也不会被销毁!
总结:就是通过StartService启动的,停止时用stopService;用bindService启动的service,停止时用unBindService。不然的话,是无法停止service的。
public class TestService extends Service {
private final static String TAG = "TestService";
private int count;
private boolean quit;
//定义onBinder方法所返回的对象
private MyBinder binder = new MyBinder();
public class MyBinder extends Binder
{
public int getCount()
{
return count;
}
}
public TestService() {
super();
}
@Override
public void onCreate() {
super.onCreate();
Log.e(TAG,"onCreate");
//创建一个线程动态地修改count的值
new Thread()
{
public void run()
{
while(!quit)
{
try
{
Thread.sleep(1000);
}catch(InterruptedException e){e.printStackTrace();}
count++;
}
};
}.start();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.e(TAG,"onBind");
return binder;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG,"onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public boolean onUnbind(Intent intent) {
Log.e(TAG,"onUnbind");
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
Log.e(TAG,"onDestroy");
super.onDestroy();
}
@Override
public void onRebind(Intent intent) {
Log.e(TAG, "onRebind");
super.onRebind(intent);
}
}
startService生命周期的调用顺序
startService(new Intent(SecondActivity.this,TestService.class));
stopService(new Intent(SecondActivity.this,TestService.class));
第一次点击启动service,走了onCreate和onStartCommand,第二、三次点击启动service方法,只执行了onStartCommand。点击停止service,执行了onDestroy。再点击启动service时,重新走onCreate和onStartCommand。
bindService的生命周期调用顺序
//保持所启动的Service的IBinder对象,同时定义一个ServiceConnection对象
private TestService.MyBinder binder;
private ServiceConnection conn = new ServiceConnection() {
//Activity与Service断开连接时回调该方法
@Override
public void onServiceDisconnected(ComponentName name) {
System.out.println("------Service DisConnected-------");
}
//Activity与Service连接成功时回调该方法
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
System.out.println("------Service Connected-------");
binder = (TestService.MyBinder) service;
}
};
//bind服务
bindService(new Intent(SecondActivity.this,TestService.class),conn, Service.BIND_AUTO_CREATE);
//停止服务
Toast.makeText(getApplicationContext(), "Service的count的值为:"+ binder.getCount(), Toast.LENGTH_SHORT).show();
unbindService(conn);
第一次点击bindService时,走了onCreate和onBind,这个时候再点击bindService是不起任何作用的。点击unbindService时,走了onUnbind和onDestroy。
使用BindService绑定Service,依次调用onCreate(),onBind()方法,
我们可以在onBind()方法中返回自定义的IBinder对象;再接着调用的是
ServiceConnection的onServiceConnected()方法该方法中可以获得
IBinder对象,从而进行相关操作;当Service解除绑定后会自动调用
onUnbind和onDestroyed方法,当然绑定多客户端情况需要解除所有 的绑定才会调用onDestoryed方法进行销毁哦!
Service与IntentService
Service中,不能执行耗时的操作,会引起ANR异常(Application Not Responding)
IntentService中,可以执行耗时的操作。 IntentService是继承与Service并处理异步请求的一个类,在IntentService中有 一个工作线程来处理耗时操作,请求的Intent记录会加入队列。
工作流程:
客户端通过startService(Intent)来启动IntentService;
我们并不需要手动地区控制IntentService,当任务执行完后,IntentService会自动停止;
可以启动IntentService多次,每个耗时操作会以工作队列的方式在IntentService的
onHandleIntent回调方法中执行,并且每次只会执行一个工作线程,执行完一,再到二这样!
IntentService的生命周期调用
创建TestService3 服务,继承与IntentService
public class TestService3 extends IntentService {
private final String TAG = "hehe";
//必须实现父类的构造方法
public TestService3()
{
super("TestService3");
}
//必须重写的核心方法
@Override
protected void onHandleIntent(Intent intent) {
//Intent是从Activity发过来的,携带识别参数,根据参数不同执行不同的任务
String action = intent.getExtras().getString("param");
if(action.equals("s1")){
Log.e(TAG,"启动service1");
} else if(action.equals("s2")){
Log.e(TAG,"启动service2");
} else if(action.equals("s3")){
Log.e(TAG,"启动service3");
}
//让服务休眠2秒
try{
Thread.sleep(2000);
}catch(InterruptedException e){e.printStackTrace();}
}
//重写其他方法,用于查看方法的调用顺序
@Override
public IBinder onBind(Intent intent) {
Log.e(TAG,"onBind");
return super.onBind(intent);
}
@Override
public void onCreate() {
Log.e(TAG,"onCreate");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG,"onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void setIntentRedelivery(boolean enabled) {
super.setIntentRedelivery(enabled);
Log.e(TAG,"setIntentRedelivery");
}
@Override
public void onDestroy() {
Log.e(TAG,"onDestroy");
super.onDestroy();
}
}
启动服务:
Intent it1 = new Intent(SecondActivity.this,TestService3.class);
Bundle b1 = new Bundle();
b1.putString("param", "s1");
it1.putExtras(b1);
Intent it2 = new Intent(SecondActivity.this,TestService3.class);
Bundle b2 = new Bundle();
b2.putString("param", "s2");
it2.putExtras(b2);
Intent it3 = new Intent(SecondActivity.this,TestService3.class);
Bundle b3 = new Bundle();
b3.putString("param", "s3");
it3.putExtras(b3);
startService(it1);
startService(it2);
startService(it3);
启动服务后
小结:
当一个后台的任务,需要分成几个子任务,然后按先后顺序执行,子任务 (简单的说就是异步操作),此时如果我们还是定义一个普通Service然后
在onStart方法中开辟线程,然后又要去控制线程,这样显得非常的繁琐;
此时应该自定义一个IntentService然后再onHandleIntent()方法中完成相关任务!