Android学习笔记五之Service.docx
- 文档编号:15870666
- 上传时间:2023-07-08
- 格式:DOCX
- 页数:29
- 大小:141.46KB
Android学习笔记五之Service.docx
《Android学习笔记五之Service.docx》由会员分享,可在线阅读,更多相关《Android学习笔记五之Service.docx(29页珍藏版)》请在冰点文库上搜索。
Android学习笔记五之Service
Android学习笔记五之Service
1、什么是Service?
什么是Service?
Service是Android系统的四大组件之一,官方文档是这样描述Service的:
AServiceisanapplicationcomponentthatcanperformlong-runningoperationsinthebackgroundanddoesnotprovideauserinterface.Anotherapplicationcomponentcanstartaserviceanditwillcontinuetoruninthebackgroundeveniftheuserswitchestoanotherapplication.Additionally,acomponentcanbindtoaservicetointeractwithitandevenperforminterprocesscommunication(IPC).Forexample,aservicemighthandlenetworktransactions,playmusic,performfileI/O,orinteractwithacontentprovider,allfromthebackground.
翻译过来就是:
服务是一个应用程序组件,可以在后台执行长时间运行的操作,不提供用户界面。
另一个应用程序组件可以启动一个服务,它将继续在后台运行,即使用户切换到另一个应用程序。
此外,一个组件可以绑定到一个服务的互动,甚至执行进程间通信(IPC)。
例如,一个服务可以处理网络交互、播放音乐、执行文件I/O、或与内容提供者进行交互,都来自后台。
2、Service的分类
按运行地点分:
本地服务(LocalService):
本地服务依附在主线程上而不是一个独立的进程,这样节约了内存资源,LocalService在同一进程中,不需要IPC和AIDL。
但是LocalService当主进程被kill掉之后,服务也会停止。
例如用于音乐播放等
远程服务(RemoteService):
RemoteService是一个独立的进程,当Activity所在的进程被kill掉之后,还会存在,可以为多个进程服务,不受进程影响。
对应进程名格式为所在包名加上你指定的android:
process字符串。
一般是系统提供的服务,这种服务会常驻内存,占用一定的资源。
RemoteService一般非常少见,并且一般都是系统服务。
按运行类型分:
前台服务:
在Notification显示正在运行图标,当服务被kill掉的时候,Notification显示的图标也会消失,对用户有一定的通知作用,例如音乐播放服务。
后台服务:
默认的服务就是后台服务,不会再通知栏显示正在运行图标,当服务被终止的时候,用户看不到效果。
某些不需要运行或者终止提示的服务,例如天气更新等
后台服务创建运行图标并且调用startForeground方法,才会使后台服务变成前台服务。
按使用方式分类:
startService启动的服务:
主要用于启动一个服务执行后台任务,不进行通信。
停止服务使用stopService,启动之后,关联的Activity销毁并不会影响Service。
bindService启动的服务:
该方法启动的服务要进行通信。
停止服务使用unbindService。
当绑定的Activity销毁的时候,Service也会销毁。
startService同时也bindService启动的服务:
停止服务应同时使用stepService与unbindService
3、Service与Thread的区别
很多时候,我们都觉得用Thread比用Service简单的多,但是为什么还会使用Service呢?
Thread:
Thread是比进程更小的单元,Thread是程序执行的最小单元,它是分配CPU的基本单位。
可以用Thread来执行一些异步的操作。
一个进程里面可以有多个Thread,Thread必须运行在进程里面
Service:
Service是Android的一种机制,当它运行的时候如果是LocalService,那么对应的Service是运行在主进程上的。
如:
onCreate,onStart这些函数在被系统调用的时候都是在主进程上运行的。
如果是RemoteService,那么对应的Service则是运行在独立进程上。
Thread是独立于Activity运行的,当一个Activity启动一个Thread的时候,只要Thread的run方法还没有执行完或者不是在Activity中停止Thread,Thread会一直执行。
这样就会产生一个问题:
当Thread还在运行,但是Activity被Finish掉了,其他的Activity不能持有当前Thread。
举个例子:
如果你的Thread需要不停地隔一段时间就要连接服务器做同步的话,该Thread需要在Activity没有启动的时候也在运行。
这个时候当你启动一个新Activity就没有办法在该Activity里面控制之前创建的Thread。
因此你便需要创建并启动一个Service,在Service里面创建、运行并控制该Thread,这样便解决了该问题(因为任何Activity都可以控制同一Service,而系统也只会创建一个对应Service的实例)。
可以把Service想象成一种消息服务,我们可以在任何有Context的地方调用Context.startService、Context.stopService、Context.bindService,Context.unbindService,来控制它,你也可以在Service里注册BroadcastReceiver,在其他地方通过发送broadcast来控制它,当然这些都是Thread做不到的。
所以我们需要Service。
4、Service的生命周期
与Activity一样,Service也有一系列的生命周期方法,我们可以实现它们来监测service状态的变化,并且在适当的时候执行适当的工作。
如下图就是Service的生命周期图
由上图可以知道,Android使用Service有两种方式,绑定启动bindService和startService。
还有一种就启动后之后绑定Service。
Service生命周期方法详解:
publicclassExampleServiceextendsService
{
intmStartMode;//indicateshowtobehaveiftheserviceiskilled
IBindermBinder;//interfaceforclientsthatbind
booleanmAllowRebind;//indicateswhetheronRebindshouldbeused
@Override
publicvoidonCreate()
{
//Theserviceisbeingcreated
}
@Override
publicintonStartCommand(Intentintent,intflags,intstartId)
{
//Theserviceisstarting,duetoacalltostartService()
returnmStartMode;
}
@Override
publicIBinderonBind(Intentintent)
{
//AclientisbindingtotheservicewithbindService()
returnmBinder;
}
@Override
publicbooleanonUnbind(Intentintent)
{
//AllclientshaveunboundwithunbindService()
returnmAllowRebind;
}
@Override
publicvoidonRebind(Intentintent)
{
//AclientisbindingtotheservicewithbindService(),
//afteronUnbind()hasalreadybeencalled
}
@Override
publicvoidonDestroy()
{
//Theserviceisnolongerusedandisbeingdestroyed
}
}
onCreate()方法:
当Service第一次被创建后立即回调该方法,该方法在Service整个生命周期中之调用一次
onStartCommand(Intentintent,intflags,intstartId)方法:
当客户端调用startService(Intent)方法时会回调,可多次调用StartService方法,但不会再创建新的Service实例,而是继续复用前面产生的Service实例,但会继续回调onStartCommand()方法!
onBind(Intentintent)方法:
此方法是Service都必须实现的方法,该方法会返回一个IBinder对象,app通过该对象与Service组件进行通信!
onUnbind(Intentintent)方法:
当该Service上绑定的所有客户端都断开时会回调该方法!
onDestroy()方法:
当Service被销毁的时候会回调该方法,该方法只会回调一次!
onRebind(Intentintent)方法:
此方法在app调用onUnbind()方法之后需要重新绑定Service的时候调用。
StartService启动Service
第一次启动会创建一个Service实例,依次调用onCreate()(onCreate方法只会调用一次)和onStartCommand()方法,此时Service进入运行状态,如果再次调用StartService启动Service,将不会再创建新的Service对象,系统会直接复用前面创建的Service对象,调用它的onStartCommand()方法!
该Service将会一直在后台运行,而不管对应程序的Activity是否在运行,直到被调用stopService,或自身的stopSelf方法。
当然如果系统资源不足,android系统也可能结束服务。
BindService启动Service
如果一个Service被某个Activity调用Context.bindService方法绑定启动,此后如果再次使用bindService绑定Service,系统不会创建新的Sevice实例,也不会再调用onBind()方法,只会直接把IBinder对象传递给其他后来增加的客户端!
不管调用bindService调用几次,onCreate方法都只会调用一次,同时onStart方法始终不会被调用。
当连接建立之后,Service将会一直运行,除非调用Context.unbindService断开连接或者之前调用bindService的Context不存在了(如Activity被finish的时候),系统将会自动停止Service,对应onDestroy将被调用。
StartService启动Service后bindService绑定
如果一个Service又被启动又被绑定,则该Service将会一直在后台运行。
并且不管如何调用,onCreate始终只会调用一次,对应startService调用多少次,Service的onStart便会调用多少次。
调用unbindService将不会停止Service,而必须调用stopService或Service的stopSelf来停止服务。
特别注意
当调用bindService绑定Service的时候,必须要在某处调用unbindService解绑Service
当使用startService的时候,必须要使用stopService停止服务
当同时用startService和bindService时,要终止Service,必须要同时调用unbindService和stopService,不管startService与bindService的调用顺序,如果先调用unbindService此时服务不会自动终止,再调用stopService之后服务才会停止,如果先调用stopService此时服务也不会终止,而再调用unbindService或者之前调用bindService的Context不存在了(如Activity被finish的时候)之后服务才会自动停止;
旋转手机屏幕的时候,默认状态下bindService会断开
当想要使用Service的时候,必须要在AndroidManifest.xml中注册。
5、IntentService
由于Service和Activity一样,都是运行在主线程中的,如果直接在Service里面执行耗时操作会ANR,所以谷歌提供了一个IntentService来处理耗时操作。
简单来说,IntentService是继承于Service并处理异步请求的一个类,在IntentService内有一个工作线程来处理耗时操作,启动IntentService的方式和启动传统Service一样,同时,当任务执行完后,IntentService会自动停止,而不需要我们去手动控制。
另外,可以启动IntentService多次,而每一个耗时操作会以workerqueue的方式在IntentService的onHandleIntent回调方法中执行,并且,每次只会执行一个workerThread,执行完第一个再执行第二个,以此类推。
而且,所有请求都在一个单线程中,不会阻塞应用程序的主线程(UIThread),同一时间只处理一个请求。
IntentService在处理事务时,还是采用的Handler方式,创建一个名叫ServiceHandler的内部Handler,并把它直接绑定到HandlerThread所对应的子线程。
ServiceHandler把处理一个intent所对应的事务都封装到叫做onHandleIntent的虚函数;因此我们直接实现虚函数onHandleIntent,再在里面根据Intent的不同进行不同的事务处理就可以了。
另外,IntentService默认实现了Onbind()方法,返回值为null。
使用IntentService需要两个步骤:
1、写构造函数
2、实现虚函数onHandleIntent,并在里面根据Intent的不同进行不同的事务处理。
这样做的好处是:
处理异步请求的时候可以减少写代码的工作量,比较轻松地实现项目的需求
注意:
IntentService的构造函数一定是参数为空的构造函数,然后再在其中调用super(“name”)这种形式的构造函数。
因为Service的实例化是系统来完成的,而且系统是用参数为空的构造函数来实例化Service的
publicclassMyIntentServiceextendsIntentService{
finalstaticStringTAG="robin";
publicMyIntentService(){
super("com.lenovo.robin.test.MyIntentService");
Log.i(TAG,this+"isconstructed");
}
@Override
protectedvoidonHandleIntent(Intentarg0){
Log.i(TAG,"beginonHandleIntent()in"+this);
try{
Thread.sleep(10*1000);
}catch(InterruptedExceptione){
e.printStackTrace();
}
Log.i(TAG,"endonHandleIntent()in"+this);
}
publicvoidonDestroy()
{
super.onDestroy();
Log.i(TAG,this+"isdestroy");
}
}
IntentService源码
packageandroid.app;
importandroid.content.Intent;
importandroid.os.Handler;
importandroid.os.HandlerThread;
importandroid.os.IBinder;
importandroid.os.Looper;
importandroid.os.Message;
publicabstractclassIntentServiceextendsService{
privatevolatileLoopermServiceLooper;
privatevolatileServiceHandlermServiceHandler;
privateStringmName;
privatebooleanmRedelivery;
privatefinalclassServiceHandlerextendsHandler{
publicServiceHandler(Looperlooper){
super(looper);
}
@Override
publicvoidhandleMessage(Messagemsg){
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
}
publicIntentService(Stringname){
super();
mName=name;
}
publicvoidsetIntentRedelivery(booleanenabled){
mRedelivery=enabled;
}
@Override
publicvoidonCreate(){
//TODO:
Itwouldbenicetohaveanoptiontoholdapartialwakelock
//duringprocessing,andtohaveastaticstartService(Context,Intent)
//methodthatwouldlaunchtheservice&handoffawakelock.
super.onCreate();
HandlerThreadthread=newHandlerThread("IntentService["+mName+"]");
thread.start();
mServiceLooper=thread.getLooper();
mServiceHandler=newServiceHandler(mServiceLooper);
}
@Override
publicvoidonStart(Intentintent,intstartId){
Messagemsg=mServiceHandler.obtainMessage();
msg.arg1=startId;
msg.obj=intent;
mServiceHandler.sendMessage(msg);
}
/**
*YoushouldnotoverridethismethodforyourIntentService.Instead,
*override{@link#onHandleIntent},whichthesystemcallswhentheIntentService
*receivesastartrequest.
*@seeandroid.app.Service#onStartCommand
*/
@Override
publicintonStartCommand(Intentintent,intflags,intstartId){
onStart(intent,startId);
returnmRedelivery?
START_REDELIVER_INTENT:
START_NOT_STICKY;
}
@Override
publicvoidonDestroy(){
mServiceLooper.quit();
}
@Override
publicIBinderonBind(Intentintent){
returnnull;
}
protectedabstractvoidonHandleIntent(Intentintent);
}
5、Service实战
通过startService启动的Service:
新建一个类继承Service
publicclassFirstServiceextendsService{
@Nullable
@Override
publicIBinderonBind(Intentintent){
returnnull;
}
在清单文件中注册Service
android: allowBackup="true" android: icon="@mipmap/ic_launcher" android: label="@string/app_name" android: supportsRtl="true" android: theme="@style/AppTheme"> name=".MainActivity"> name="android.intent.action.MAIN"/> name="android.intent.category.LAUNCHER"/> name=".Service.FirstService"/>
在Activity中调用startService方法
btn_start_service=(Button)findViewB
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Android 学习 笔记 Service