Service没有界面的Activity
Local Service
相信许多对很多朋友来说,Service是再熟悉不过了,毕竟是Android的四大组件之一,在一个应用中扮演了一个很重要的角色.
Service作为Android四大组件之一,在每一个应用程序中都扮演着非常重要的角色。它主要用于在后台处理一些耗时的逻辑,或者去执行某些需要长期运行的任务。必要的时候我们甚至可以在程序退出的情况下,让Service在后台继续保持运行状态。我们都知道,
Activity中是不能执行耗时的操作的,如果执行了耗时的操作的话
,会引起线程的阻塞,导致界面无法响应,用户的事件,这对用户的体验是非常差的,也会导致著名的ANR异常,毕竟Activity只是用来显示绚丽的界面的,和响应用户事件的,那么如果我们想执行一些耗时的
操作呢,这时Service就闪亮登场了.
还有就是,在一些情况下,我们退出应用时,也要去处理一些逻辑,
最常见的就是下载更新包,或者下载电影之类的.单纯的Activity是不能完成这些耗时的操作的.或者去执行某些长期运行的任务.
**不过虽然Service几乎被每个程序员所熟知,但也不是每个人都已经将Service的各个知识点都掌握的非常透彻,今天我就将带着大家进行一次
,比较全面的了解,希望对那些刚加入Android的程序员的人一些帮助.**
首先 Service是一个应用组件, 它用来在后台完成一个时间跨度比较大的工作且没有关联任何界面
Service可以干嘛
访问网络
播放音乐
文件IO操作
大数据量的数据库操作
Service的特点
Service在后台运行,不用与用户进行交互
即使程序被切换到后台,或者用户打开新的应用,服务仍可运行
服务并非运行在独立的进程中,而是依赖于创建服务的应用程序进程。如果某个应用进程被杀掉,该服务也会停止.在默认情况下,Service运行在应用程序进程的主线程(UI线程)中,如果需要在Service中处理一些网络连接等耗时的操作,那么应该将这些任务放在分线程中处理,避免阻塞用户界面.
它无法与用户直接进行交互、它必须由用户或者其他程序显式的启动、它的优先级比较高,它比处于前台的应用优先级低,但是比后台的其他应用优先级高,这就决定了当系统因为缺少内存而销毁某些没被利用的资源时,它被销毁的概率很小哦
Service与Activity的区别
1.Activity:
Activity对应一个界面
应用退出, Activity对象就会死亡
应用再次进入, 启动的Activity对象是重新创建的
2 Service
不与任何界面关联,绝不会到前台来
应用退出, Service仍在运行
应用再次进入, 启动的Service还是前面运行的Service对象
3.Activity 与 Service 的选择标准:
如果某个应用程序组件需要运行时向用户呈现某种界面,或者该程序需要与用户交互,就需要使用Activity,否则就应该考虑使用Service。
区别Service与Thread?
1. Service
用来在后台完成一个时间跨度比较大的工作的应用组件
Service的生命周期方法运行在主线程, 如果Service想做持续时间比较长的工作, 需要启动一个分线程(Thread)
应用退出: Service不会停止
应用再次进入: 可以与正在运行的Service进行通信
2. Thread
用来开启一个分线程的类, 做一个长时间的工作
Thread对象的run()在分线程执行
应用退出: Thread不会停止
应用再次进入: 不能再控制前面启动的Thread对象
Service的分类
1.Local Service(本地服务)
Service对象与Service的启动者在同个进程中运行, 两者的通信是进程内通信
2.Remote Service(远程服务)
Service对象与Service的启动者不在同一个进程中运行, 这时存在一个进程间通信的问题, Android专门为此设计了AIDL来实现进程间通信(后面会讲AIDL)
Service的基本使用
1.写一个类继承与Service并重写父类相应的方法这要根据你的业务逻辑重写对应的方法
`/**
* Created by li_zh on 2016/7/12.
* 作者:李杰
* 邮箱:577124196@qq.com
*/
public class Myservice extends Service{
@Override
public void onRebind(Intent intent) {
super.onRebind(intent);
}
@Override
public void onCreate() {
super.onCreate();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
`
Service 的两种启动方式与相应的生命周期
Context.startService(Intent service);
相关的生命周期方法
onCreate()->onStartCommand();->onDestory();
- Context.bindService(Intent service, ServiceConnection conn, int flags);
相关的生命周期方法
onCreate()->onBind()->onUnBind()->onDestory();
有启动Service就有停止服务,要不然就一直在后台运行太耗内存了
如果你是startService()的方式启动的服务那么你可以调用Context.stopService()来停止服务.
如果是通过bind的方式启动的服务那么你可以调用Context.unBindService()来解绑服务
注意:
1、你应当知道在调用 bindService 绑定到Service的时候,你就应当保证在某处调用 unbindService 解除绑定(尽管 Activity 被 finish 的时候绑定会自动解除,并且Service会自动停止);
2、你应当注意 使用 startService 启动服务之后,一定要使用 stopService停止服务,不管你是否使用bindService;
3、同时使用 startService 与 bindService 要注意到,Service 的终止,需要unbindService与stopService同时调用,才能终止 Service,不管 startService 与 bindService 的调用顺序,如果先调用 unbindService 此时服务不会自动终止,再调用 stopService 之后服务才会停止,如果先调用 stopService 此时服务也不会终止,而再调用 unbindService 或者 之前调用 bindService 的 Context 不存在了(如Activity 被 finish 的时候)之后服务才会自动停止;
4、当在旋转手机屏幕的时候,当手机屏幕在“横”“竖”变换时,此时如果你的 Activity 如果会自动旋转的话,旋转其实是 Activity 的重新创建,因此旋转之前的使用 bindService 建立的连接便会断开(Context 不存在了),对应服务的生命周期与上述相同。
5、在 sdk 2.0 及其以后的版本中,对应的 onStart 已经被否决变为了 onStartCommand,不过之前的 onStart 任然有效。这意味着,如果你开发的应用程序用的 sdk 为 2.0 及其以后的版本,那么你应当使用 onStartCommand 而不是 onStart。
官方提供的生命周期图
扩展
情景如下:
我们会同时调用startService() 和 bindService():
因为在有些时候我们会有这样的要求,通过startService来启动一个服务
能够在Activity销毁时Service依然能够运行,通过bindService()来获取一个IBinder的对象(涉及到之间的通信问题这里暂不展开)来操控Service.
比如播放音乐类型的服务.我们希望退出应用时也能继续听音乐.- 而这时的生命周期是
如果是先startService()再onBind()
onCreate()->onStartCommand()->onBind();如果是先onBind()再onStartService()
onCreate()->onBind()-onStartcommand();而这时如果只是stopService()或者只unBindService();
服务是不会执行onDestory()方法的也就是Service不会销毁这样就达到了我们的需求;如果想要停止服务需要同时调用stopService()和onUnBind()才能停止服务;
官方的解释是:
When the last client unbinds from the service, the system destroys the service (unless the service was also started by startService()).
>
当最后一个客户解绑的服务,系统销毁服务(除非服务也开始startservice())
Note that if a stopped service still has ServiceConnection objects bound to it with the BIND_AUTO_CREATE set, it will not be destroyed until all of these bindings are removed.
注意,如果停止服务还具有serviceconnection对象绑定到它的bind_auto_create集,它不会直到所有这些绑定被摧毁。
如图:
- onRebind()的调用时机
onRebind()方法执行的时机是Service在内存中已经存在,然后使用bindService()方法再次与Service取得通信,这时onRebind()方法被调用。
当我们在Service里执行了耗时的操作时,时间超过了10秒也会引起ANR异常.
既然Service里也不能执行时间过长的操作那么我们该把那些特别耗时的操作写在哪里呢
方式一:
当我们在Service执行耗时任务时我们可以自己开启一个线程,
在改线程里执行相关的耗时任务.方式二:
我们可以使用IntentService
我们先看下源码
private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler;
‘@Override
public void onCreate() {
// TODO: It would be nice to have an option to hold a partial wakelock
// during processing, and to have a static startService(Context, Intent)
// method that would launch the service & hand off a wakelock.super.onCreate();
HandlerThread thread = new HandlerThread(“IntentService[” + mName + “]”);
thread.start();mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}’当onCreate()时就已经有了一个workthread和lopper来管理线程的通信
这样我们就不用担心对UI线程的阻塞了.IntentService已经实现了.
` private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}@Override public void handleMessage(Message msg) { onHandleIntent((Intent)msg.obj); stopSelf(msg.arg1); }
当有消息时回调用onHandler()
`protected abstract void onHandleIntent(Intent intent);
而这个方法又是抽像的所以我们只需重写这个方法完成自己的逻辑就行了.
而当我们在onHandlerIntent()里的逻辑执行完成后会调用stopSelf(msg.arg1);
总结
- Service 是运行在主进程的 main 线程上的。如:onCreate,onStart 这些函数在被系统调用的时候都是在主进程的 main 线程上运行的。请不要把 Service 理解成线程,它跟线程半毛钱的关系都没有!
1). 被启动的服务的生命周期:如果一个Service被某个Activity 调用 Context.startService 方法启动,那么不管是否有Activity使用bindService绑定或unbindService解除绑定到该Service,该Service都在后台运行。如果一个Service被startService 方法多次启动,那么onCreate方法只会调用一次,onStart将会被调用多次(对应调用startService的次数),并且系统只会创建Service的一个实例(因此你应该知道只需要一次stopService调用)。该Service将会一直在后台运行,而不管对应程序的Activity是否在运行,直到被调用stopService,或自身的stopSelf方法。当然如果系统资源不足,android系统也可能结束服务。
2). 被绑定的服务的生命周期:如果一个Service被某个Activity 调用 Context.bindService 方法绑定启动,不管调用 bindService 调用几次,onCreate方法都只会调用一次,同时onStart方法始终不会被调用。当连接建立之后,Service将会一直运行,除非调用Context.unbindService 断开连接或者之前调用bindService 的 Context 不存在了(如Activity被finish的时候),系统将会自动停止Service,对应onDestroy将被调用。
3). 被启动又被绑定的服务的生命周期:如果一个Service又被启动又被绑定,则该Service将会一直在后台运行。并且不管如何调用,onCreate始终只会调用一次,对应startService调用多少次,Service的onStart便会调用多少次。调用unbindService将不会停止Service,而必须调用 stopService 或 Service的 stopSelf 来停止服务。
4). 当服务被停止时清除服务:当一个Service被终止(1、调用stopService;2、调用stopSelf;3、不再有绑定的连接(没有被启动))时,onDestroy方法将会被调用,在这里你应当做一些清除工作,如停止在Service中创建并运行的线程。
IntentService是继承Service的,那么它包含了Service的全部特性,当然也包含service的生命周期,那么与service不同的是,IntentService在执行onCreate操作的时候,内部开了一个线程,去你执行你的耗时操作。
使用intentService与service有什么不同呢
(1)直接 创建一个默认的工作线程,该线程执行所有的intent传递给onStartCommand()区别于应用程序的主线程。
(2)直接创建一个工作队列,将一个意图传递给你onHandleIntent()的实现,所以我们就永远不必担心多线程。
(3)当请求完成后自己会调用stopSelf(),所以你就不用调用该方法了。
(4)提供的默认实现onBind()返回null,所以也不需要重写这个方法。so easy啊
(5)提供了一个默认实现onStartCommand(),将意图工作队列,然后发送到你onHandleIntent()实现.
最后就是Service一定要在功能清单里注册
一些唠叨
博主还很菜!所以博客写的不是很好.语言组织的不是很好,
在这希望大家谅解,也希望多多少少对大家有一些帮助.还有就是博客更新的话周期可能会长些!