安卓四大组件之服务,安卓四大组件
Service 是Android 中的(四大)组件之一。服务是没有界面的组件,运行在后台,服务是运行在当前应用程序进程里。如果有耗时的操作,不想有界面、而且还不想程序退出就停止运行的逻辑,放在服务里。要注意的是,服务也是运行在主线程中,如果有耗时操作,要放在子线程里,如果服务被系统杀死了,会默认重启。另外,组件也可以通过绑定的形式跟一个Service进行交互,甚至完成进程间通信。比如:Service 可以在后台处理网络传输、播放音乐、进行I/O 流的读写或者跟内容提供者进行交互。startService()和bindService()是开启服务的两种方式,startService()不能调用服务里的方法,不可以与服务进行通信,服务一旦开启,会长时间在后台运行,与开启在不再有关系, 开启在退出了,服务还是在运行的,而且不能调用服务里的方法;bindService()可以间接的调用服务里的方法,可以与服务进程通信,服务开启了是和开启在的生命周期绑定的,如果开启在关闭了,服务也就关闭了, 开启者可以间接的调用服务里的方法。如果服务同时被开启和绑定,那么服务就停不掉了,需要解除绑定服务才能停止服务。需要服务长期在后台运行,还需要调用服务里的方法,用混合方式开启服务,即采用两种方式,但调用方式需要严格的顺序。首先,用start方式开启服务,目的是保证服务在后台能够长时间运行;其次,用bind方式绑定服务,绑定了服务,方便调用服务里的方法;然后解绑时,要先用unBind方式解绑,最后才stop方式停止服务。
以上就是对服务的基本描述,接下来实现服务的具体操作。首先,需要明确一下服务的具体操作步骤。
startService()的方式开启服务的大体流程如下:
1. 写一个类继承 Service;
2. 重写onCreate()方法;
3. 在清单文件的下面声明service,在name标签中写下服务的包名加类名;
bindService()的方式绑定服务的具体写法:
1. 创建服务类, 继承 Service;
2. 定义一个接口,暴露对外提供的方法;
public interface IService{ public void callServiceMethed(); }
3. 在服务类里定义代理对象,定义一个方法可以间接的调用服务的方法, 这样写可以防止不想被暴露的方法被别人调用了,将希望被调用的方法写在接口中,其他方法不被其他类调用;
private class MyBinder extends Binder implements IService{ public void callServiceMethed(){ 调用服务的方法 } ... }
4. 在onBinder方法里返回代理对象,如果不返回,调用方拿到的对象就是空的
public IBinder onBind(Intent intent) { return new MyBinder(); }
5. 创建类实现 ServiceConnection,实现里面的两个方法
private class MyConn implements ServiceConnection{ @Override public void onServiceConnected(ComponentName name, IBinder service) { //当服务连接成功时候调用 } @Override public void onServiceDisconnected(ComponentName name) { //当服务断开连接时调用 } }
6. activity采用绑定的方式开启服务,bindService()方法绑定服务;
7. 调用代理对象的方法,间接的调用了服务里的方法
接下来了解一下服务的生命周期
跟Activity 一样,Service 也是有生命周期的,不一样的是Service 的生命周期,从它被创建开始,到它被销毁为止,可以有两条不同的路径:标准开启模式和绑定模式。两种生命周期的可以用下面箭头表示:
标准开启模式的生命周期:
startService()->onCreate() -> onstartcommand() -> onDestroy()
绑定模式的生命周期:
bindService()->onBind() -> onunBind() -> onDestroy()
被开启的service 通过其他组件调用startService()被创建。这种service 可以无限地运行下去,必须调用stopSelf()方法或者其他组件调用stopService()方法来停止它。当service 被停止时,系统会销毁它。用start方法开启服务,服务只会被创建一次,执行一次onCreate方法,一旦服务创建完成,后续调用start去开启服务只会执行onstart和onstartcommand方法,当调用了stop方法,服务只会调用一次onDestroy方法。
被绑定的service 是当其他组件模拟一个客户时,调用bindService()来创建的。客户可以通过一个IBinder接口和service 进行通信。客户可以通过unbindService()方法来关闭这种连接。一个service 可以同时和多个客户绑定,当多个客户都解除绑定之后,系统会销毁service。你可以和一个已经调用了startService()而被开启的service 进行绑定。比如,一个后台音乐service 可能因调用startService()方法而被开启了,稍后可能用户想要控制播放器或者得到一些当前歌曲的信息,可以通过bindService()将一个activity 和service 绑定。这种情况下,stopService()或stopSelf()实际上并不能停止这个service,除非所有的客户都解除绑定。
了解服务的生命周期是为了更好的理解服务在整个工程下的运行原理。因此有必要了解一下安卓中进程的工作原理。
在Android 中进程优先级由高到低,依次分为:前台进程(Foreground process),可视化进程(Visible process),服务进程(Service process),后台进程(Background process),空进程(Empty process)。下面一次给出每一种进程的概念和应用场景。
前台进程(Foreground process): 用户正在操作的应用程序进程叫做前台进程。通常情况下,在任何时候系统只存在一小部分前台进程。这些进程只会作为最后的手段才会被杀死,即当内存不足以继续运行他们的时候。在这个时刻,设备已经达到内存分页状态,当系统达到内存分页状态时只能通过虚拟地址访问内存,可理解为达到这个状态时系统已经无法继续分配新的内存空间即可,因此杀死一些前台进程,释放内存空间以保证应用能够继续响应用户的交互是必要的手段。
可视化进程(Visible process): 用户已经不能操作这个应用程序了,但是用户还能看到应用程序界面。一个可视进程被认为是极其重要的并且一般不会被系统杀死,除非为了保证所有的前台进程去运行不得已为之。
服务进程(Service process): 应用程序服务在后台运行。一个拥有正在运行的Service,并且该Service 是被startService()方法启动起来的进程,并且该进程没有被归类到前面的两种(前置进程和可视进程)类型,那么该进程就是服务进程。尽管服务进程没有与用户可见的控件直接绑定,但是这些进程干的工作依然是用户关心的(比如在后台播放音乐或者从网络上下载数据),因此系统保留这些进程一直运行除非系统没有足够的内存去运行前台进程和可视进程。
后台进程(Background process):应用程序界面被用户最小化。一个拥有对用户不可见的Activity,该Activity 已经被执行了onStop()方法进程叫做后台进程。后台进程对用户体验没有直接的影响,并且系统会在任何需要为前台进程,可视进程,或服务进程申请内存的时候杀死后台进程。通常系统中运行着大量的后台进程,这些后台进程保存在一个LRU(最少最近使用的)列表中,使用LRU 规则是为了保证让最近被用户使用的Activity 进程最后被杀死,就是谁最近被使用了,谁最后再被杀死。如果一个Activity 正确实现了它的生命周期方法,并且保存了它的状态,通常这个状态是系统自动保存的,那么当系统杀死它的进程的时候是对用户的体验没有看得见的影响的,因为当用户导航到之前的Activity 的时候,这个Activity 会自动恢复之前保存的视图状态。查看Activity 文档去获取更多关于Activity状态的保存和恢复信息。
空进程(Empty process): 应用程序没有任何的activity和service运行。不拥有任何系统