Service是Android四大组件之一,与Activity很相似。
一、Service基础
1、Service与Activity比较
相同点:
都具有生命周期的概念;
需要继承相应的父类(Activity extends Activity;Service extends Service)
需要在AndroidManifest.xml中进行配置,且都能通过intent-filter进行过滤
都是从Context派生而来
不同点:
service没有界面,一直在后台运行
2、创建配置Service的基本套路
开发Service总体来说需要两个步骤:
a、定义一个继承Service的子类
b、在AndroidManifest.xml中配置该Service
3、Service生命周期方法介绍
IBinder onBind(Intent intent):该方法是Service子类必须实现的方法。方法返回一个IBinder对象,程序可以通过该对象与Service进行通信。
void onCreate():当该Service第一次被创建后将立即回调该方法。
void onDestroy():当该Service被关闭之前将回调该方法。
void onStartCommand(Intent intent,int flags,int startId):每次客户端调用startService(Intent)方法启动该Service时都会回调该方法。
boolean onUnbind(Intent intent): 当该Service上绑定的所有客户端都断开连接时将会回调该方法。
4、Service的启动和停止
Android中运行Service有两种方式:
a、通过Context的startService(Intent)启动,通过该方法启动Service,访问者与Service之间没有关联,即使访问者退出了,Service仍然运行。
第一次调用startService(Intent)时,会回调Service的onCreate()方法,之后再次调用startService(Intent)时,onCreate()方法不执行,但是每次都会执行onStartCommand(Intent intent,int flags,int startId);通过startService()启动的Service,必须通过stopService()来停止。不论之前调用了几次start,调用一次stop即可。
b、通过Context的bindService()启动,通过该方法启动Service,访问者与Service绑定在一起,访问者一旦退出,Service也就终止(此处应该注意,不同的activity调用多次bindService()时,需要所有的activity都退出后,Service才会终止)。
同一个activity多次调用bindService()绑定同一个Service时,onBind()方法只被回调一次。
调用unbindService()解除绑定。
绑定方式时,可以实现组件与Service的交互。
5、Service的生命周期
该图描述了启动Service的两种方式以及它们的生命周期。service与activity一样都存在与当前进程的主线程中,所以,一些阻塞UI的操作,比如耗时操作不能放在service里进行,比如另外开启一个线程来处理诸如网络请求的耗时操作。如果在service里进行一些耗CPU和耗时操作,可能会引发ANR警告,这时应用会弹出是强制关闭还是等待的对话框。所以,对service的理解就是和activity平级的,只不过是看不见的,在后台运行的一个组件,这也是为什么和activity同被说为Android的基本组件。另外一个参考图片,如下:
二、Service应用
1、基本应用
a、start方式:
1、定义Service,重写父类方法
public class MyService extends Service{
Override onCreate,onStartCommand,onDestroy
}
2、activity中调用start
public class MyserviceActivity extends Activity{
...
Intent intent=new Intent(this,MyService.class);
startService(intent);
...
}
3、AndroidManifest.xml中配置service
<service android:name="com.example.service.MyService" > </service>
b、bind方式:
如果Service和访问者之间需要进行方法调用或者数据交换,应该使用bindService()和unbindService()方法启动、关闭Service。
bindService的完整方法签名:bindService(Intent service,ServiceConnection conn,int flags),参数解释如下:
service:通过Intent指定需要启动的service
conn:ServiceConnection对象,用于监听访问者与Service之间的连接情况。成功绑定时,将回调其onServiceConnected();service所在的宿主进程由于异常或其他原因终止,导致service与访问者之间的连接断开时,回调其onServiceDisconnected()。其中,主动unbind时,onServiceDisconnected()不被执行。
flags: 指定绑定时如果service还未创建,是否自动创建Service。0,不自动创建;BIND_AUTO_CREATE,自动创建。
Service类的IBinder onBinde(Intent intent)方法,在绑定本地service时,返回的IBinder对象将会传给ServiceConnection对象的onServiceConnected(ComponentName name,IBinder service)方法的service参数,这样访问者就可以通过IBinder对象与service进行通信。通常,在开发中,采用继承Binder的方式实现自己的IBinder对象。
1、实现自定义Binder,可以在Service实现类中采取内部类的方式实现
public class MyBinder extends Binder {
public int getCount() {
return count;
}
}
2、实现Service,定义成员变量Binder,并在onBinder中返回。
public class MyService extends Service {
private MyBinder binder = new MyBinder();
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return binder;
}
}
3、activity中定义ServiceConnection,并在onServiceConnected()中获取onBind()返回的Binder实例,用于方法调用或数据获取。
public class MyserviceActivity extends Activity{
private MyService.MyBinder service;//用于bind时,activity与service进行通信
private ServiceConnection conn=new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
Log.i(tag, "service disconnnect");
}
/*
* IBinder对象可以实现与service的通信
*/
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
Log.i(tag, "service connect");
MyserviceActivity.this.service=(MyService.MyBinder)service;
}
};
}
2、IntentService应用
IntentService是Service的子类,比普通Service增加了额外的功能。
Service本身存在如下两个问题:
Service不会专门启动单独的一个进程,与应用处于同一个进程;
Service不是专门的一个新的线程,不应该在Service中执行耗时任务,否则会出ANR。
IntentService使用队列的方式将请求的Intent加入队列,然后开启一个worker thread(线程)来处理队列中的Intent,对于异步的startService请求,IntentService会处理完成一个之后再处理第二个,每一个请求都会在一个单独的worker thread中处理,不会阻塞应用程序的主线程,这里就给我们提供了一个思路,如果有耗时的操作与其在Service里面开启新线程还不如使用IntentService来处理耗时操作。而在一般的继承Service里面如果要进行耗时操作就必须另开线程,但是使用IntentService就可以直接在里面进行耗时操作,因为默认实现了一个worker thread。对于异步的startService请求,IntentService会处理完成一个之后再处理第二个。
IntentService具有如下特征:
创建单独的线程处理所有Intent请求;
创建单独的线程处理onHandleIntent()方法实现的代码;
处理完所有请求后,IntentService会自动停止;
onBind()方法提供了默认实现,默认返回null;
onStartCommand()方法提供了默认实现,将intent插入到工作队列中;
补充说明:
Android中的Service是用于后台服务的,当应用程序被挂到后台的时候,为了保证应用某些组件仍然可以工作而引入了Service这个概念,那么这里面要强调的是Service不是独立的进程,也不是独立的线程,它是依赖于应用程序的主线程的,也就是说,在更多时候不建议在Service中编写耗时的逻辑和操作,否则会引起ANR。
那么我们当我们编写的耗时逻辑,不得不被service来管理的时候,就需要引入IntentService,IntentService是继承Service的,那么它包含了Service的全部特性,当然也包含service的生命周期,那么与service不同的是,IntentService在执行onCreate操作的时候,内部开了一个线程,去你执行你的耗时操作。
应用场景:
在Android开发中,我们或许会碰到这么一种业务需求,一项任务分成几个子任务,子任务按顺序先后执行,子任务全部执行完后,这项任务才算成功。那么,利用几个子线程顺序执行是可以达到这个目的的,但是每个线程必须去手动控制,而且得在一个子线程执行完后,再开启另一个子线程。或者,全部放到一个线程中让其顺序执行。这样都可以做到,但是,如果这是一个后台任务,就得放到Service里面,由于Service和Activity是同级的,所以,要执行耗时任务,就得在Service里面开子线程来执行。那么,有没有一种简单的方法来处理这个过程呢,答案就是IntentService。
3、跨进程应用