关于android组件service概述与绑定
Service详解
作为一款多任务操作系统,如果不能运行后台服务,显然说不过去,Android 当然提供了运行后台程序的方法。而且非常简单易用,只不过有一些小问题需要注意,这个主题分为两部分,第一部分是如何实现一个Service以及他的生命周期,第二部分是对于一个个后台服务应该注意的事项。我们开始吧!
创建服务类
所谓的服务,在Android里被称做 Service,只要继承 android.app.Service 这个抽象类,并且实现其中几个方法就可以了。
服务的生命周期
有了 Service 类我们如何启动他呢,有两种方法:
Context.startService()
Context.bindService()
在同一个应用任何地方调用 startService() 方法就能启动 Service 了,然后系统会回调 Service 类的 onCreate() 以及 onStart() 方法。这样启动的 Service 会一直运行在后台,直到 Context.stopService() 或者 selfStop() 方法被调用。另外如果一个 Service 已经被启动,其他代码再试图调用 startService() 方法,是不会执行 onCreate() 的,但会重新执行一次 onStart() 。
另外一种 bindService() 方法的意思是,把这个 Service 和调用 Service 的客户类绑起来,如果调用这个客户类被销毁,Service 也会被销毁。用这个方法的一个好处是,bindService() 方法执行后 Service 会回调上边提到的 onBind() 方发,你可以从这里返回一个实现了 IBind 接口的类,在客户端操作这个类就能和这个服务通信了,比如得到 Service 运行的状态或其他操作。如果 Service 还没有运行,使用这个方法启动 Service 就会 onCreate() 方法而不会调用 onStart()。
与 Service 通信并且让它持续运行
如果我们想保持和 Service 的通信,又不想让 Service 随着 Activity 退出而退出呢?你可以先 startService() 然后再 bindService() 。当你不需要绑定的时候就执行 unbindService() 方法,执行这个方法只会触发 Service 的 onUnbind() 而不会把这个 Service 销毁。这样就可以既保持和 Service 的通信,也不会随着 Activity 销毁而销毁了。
提高 Service 优先级
Android 系统对于内存管理有自己的一套方法,为了保障系统有序稳定的运信,系统内部会自动分配,控制程序的内存使用。当系统觉得当前的资源非常有限的时候,为了保 证一些优先级高的程序能运行,就会杀掉一些他认为不重要的程序或者服务来释放内存。这样就能保证真正对用户有用的程序仍然再运行。如果你的 Service 碰上了这种情况,多半会先被杀掉。但如果你增加 Service 的优先级就能让他多留一会,我们可以用 setForeground(true) 来设置 Service 的优先级。
为什么是 foreground ? 默认启动的 Service 是被标记为 background,当前运行的 Activity 一般被标记为 foreground,也就是说你给 Service 设置了 foreground 那么他就和正在运行的 Activity 类似优先级得到了一定的提高。当让这并不能保证你得 Service 永远不被杀掉,只是提高了他的优先级。
有一个方法可以给你更清晰的演示,进入 $SDK/tools 运行命令
返回的一大堆东西,观察 oom_adj 的值,如果是大于 8 一般就是属于 backgroud 随时可能被干掉,数值越小证明优先级越高,被干掉的时间越晚。你看phone的程序是 -12 说明电话就是电话,其他什么都干了了,也的能接电话对吧。另外还有一个 -100 的,更邪乎因为是 system 如果他也完蛋了,你得系统也就挂了,嘿嘿。
用其他方式启动 Service
其实不光能从 Activity 中启动 Service ,还有一个很有用的方法是接收系统的广播,这就要用到 Receiver 。在 Mainfest 文件中配置你得 Receiver 能接收什么样的广播消息,那么即使你得程序没有显示给用户,你的 Service 也能启动。你要做的就是继承 android.content.BroadcastReceiver ,然后实现 onReceive(Context context, Intent intent) 方法,就可以启动你得 Service 了。这里不能 bindService 因为一个 Receiver 是一个短暂存在的对象,所以 bind 是没有什么意义的
Service的绑定和解绑
1、绑定服务
1.1绑定方式
通过服务链接(ServiceConnection)或直接获取Service中状态和数据信息
服务链接能够获取Service的对象,因此绑定Service的组件可以调用
Service中的实现的函数
使用Service的组件通过Context.bindService()建立服务链接,通过
Context.unbindService()停止服务链接
如果在绑定过程中Service没有启动,Context.bindService()会自
动启动Service
同一个Service可以绑定多个服务链接,这样可以同时为多个不同的
组件提供服务
1.2如何绑定service?
step1.新建一个类MyService,继承Service
step2.在Manifest.xml文件中声明<service android:name=".MyService"/>
step3.绑定
复制代码
Intent intent = new Intent(context,MyService.class);
ServiceConnection conn = new ServiceConnection(){
public void onServiceDisconnected(ComponentName name) {
Log.i("Service", "onServiceDisconnected===");
}
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i("Service", "onServiceConnected===");
}
}
context.bindService(intent,conn,Context.BIND_AUTO_CREATE);
调用者通过bindService()函数绑定服务
并在第1个参数中将Intent传递给bindService()函数,声明需要启动的Service
第3个参数Context.BIND_AUTO_CREATE表明只要绑定存在,就自动建立
Service;同时也告知Android系统,这个Service的重要程度与调用者相同,
除非考虑终止调用者,否则不要关闭这个Service
解除绑定
context.unBindService(conn);
说明:
1.unbindService(conn)//不可以多次调用
2.关于ServiceConnection的两个方法:
当连接上service时,会调用onServiceConnected方法
当连接上后,service被后台停止,那么此时会调用onServiceDisconnected方法
1.3绑定Service的生命周期
绑定:如果service没被创建,那么调用一次onCreate(),然后调用onBind(),
多次绑定时,不会多次调用onBind()
解除绑定:调用onUnbind(),然后onDestory().不可以多次调用unbindService()方法解除绑定。
1.4启动方式和绑定方式的结合
这两种使用方法并不是完全独立的,在某些情况下可以混合使用以MP3播放器为例,在后台的工作的Service通过Context.startService()启动某个特定音乐播放,但在播放过程中如果用户需要暂停音乐播放,则需要通过Context.bindService()获取服务链接和Service对象,进而通过调用Service的对象中的函数,暂停音乐播放过 程,并保存相关信息。在这种情况下,如果调用Context.stopService()并不能够停止Service,需要在所有的服务链接关闭后,Service才能够真正的停止
生命周期:
第一次点击:不管是startService还是bindService,如果service还未存在,那么会调用 onCreate,之后如果是startService那么调用onStartCommand(),如果是bindService那么会调用onBind()
之后,如果再调startService(),那么会调用onStartCommand();如果再调用bindService那么如果第一次点击是bindService,那么就不会调用onBind(),否则什么方法都不会被调用。
当bindService后,不能stopService,需要通过unBindService()来解除绑定。
只是startService()后,不可以通过unBindService()来销毁service
service和Activity处于同一个线程。
1.5服务绑定
通过bindService()函数绑定Servcie时, onCreate()函数和onBinde()函数将先后被调用通过unbindService()取消绑定Servcie时,onUnbind()函数将被调用,如果onUnbind()函数的返回true,则表示在调用者绑定新服务时,onRebind()函数将被调用
取消绑定仅需要使用unbindService()方法,并将ServiceConnnection传递给unbindService()方法 需注意的是unbindService()方法成功后,系统并不会调用onServiceDisconnected(),因为onServiceDisconnected()仅在意外断开绑定时才被调用
1.6 Service的原理和用途
startService()的目的是回调onStart()方法,onCreate() 方法是在Service不存在的时候调用的,如果Service存在(例如之前调用了bindService,那么Service的onCreate方法已经调用了)那么startService()将跳过onCreate
() 方法。bindService()目的是回调onBind()方法,它的作用是在Service和调用者之间建立一个桥梁,并不负责更多的工作(例如一个Service需要连接服务器的操作),一般使用bindService来绑定到一个现有的Service(即通过
StartService启动的服务)。