记《第一行代码》读后感---Service服务

来源:互联网 发布:查看店铺数据的插件 编辑:程序博客网 时间:2024/06/11 01:48

Service 简介:
“Service” 意思即“服务”的意思, Service是Android中实现程序后台运行的解决方案,它适合用于执行不需要和用户交互而还要求长期运行的任务。Service运行在后台,它是不可见的、无界面的程序。Service的运行不依赖于任何用户界面,承担着静悄悄的不为人所注意的工作,即使当程序被切换到后台,或者用户打开了另外一个应用程序,服务仍然能够保持正常运行。
但是,Service并不是运行在一个独立的进程当中的,而是依赖于创建服务时所在的应用程序进程。另外,不要被Service的后台概念所迷惑,Service不会自动开启线程,所有的代码都默认运行在主线程当中。使用Service时,如果担心主线程被阻塞,就需要在Service的内部手动创建一个子线程来执行任务。(服务不开启线程执行耗时操作也会产生ANR)
Service可以在很多场合的应用中使用,比如播放多媒体的时候用户启动了其他Activity,这个时候程序要在后台继续播放;比如检测SD卡上文件的变化;再或者在后台记录用户的地理信息位置的改变;或者启动一个服务来运行并一直监听某种动作等等。
Service概念的总结:
Service在后台运行,不可以与用户直接交互;
一个服务不是一个单独的进程。服务对象本身并不意味着它是在自己的进程中运行,除非另有规定,否则它与运行程序是同在一个进程中;
一个服务不是一个单独的线程。Service和其他组件一样,默认情况下,Service中的所有代码都是运行在主线程中;
Service存在的价值虽然不如Activity那么清晰。但是一般都让Service执行耗时较长的操作。例如:播放音乐、下载文件、上传文件等等。但是因为Service默认运行在主线程中,因此不能直接用它来做耗时的请求或者动作,最好在Service中启动新线程来运行耗时的任务;
需要通过某一个Activity/BroadCastReceiver或其他Context对象来启动Service。context.startService() 或 context.bindService();
Service很大程度上充当了应用程序后台线程管理器的角色。(如果Activity中新开启一个线程,当该Acitivyt关闭后,该线程依然在工作,但是与开启它的Activity失去联系。也就是说此时的这个线程处于失去管理的状态。但是使用Service,则可以对后台运行的线程有效地管理)
对于Activity来说,Service管理线程更为容易
为什么不使用后台线程而使用Service?

1、Service可以放在独立的进程中,所以更安全;
2、使用Service可以依赖现有的binder机制,不需要在应用层面上处理线程同步的繁杂工作;
3、系统可以重新启动异常死去的Service。(是不会影响用户的UI操作的)

Service 与 Activity 的相同点与不同点:
不同点:Activity是与用户交互的组件,即可以看到UI界面,而Service是在后台运行、无需界面;
相同点:使用Activity 时我们需要在配置文件中声明标签,同样的使用Service 也需要在配置文件中声明标签。都具有一定的生命周期。

根据启动方式将本地服务分为:启动服务Started Service和绑定服务Bound Service。【重点】
Started Service:被启动的服务
被启动的服务是由其它组件调用startService()方法而启动的,该方法会导致被启动服务的生命周期方法onStartCommand()被回调。当服务是被启动状态后,其生命周期与启动它的组件无关,即使启动服务的组件(Activity,BroadcastReceiver)已经被销毁,该服务还可以在后台无限期运行。除非调用stopSelf()或stopService()来停止该服务。
Bound Service:被绑定的服务
绑定服务是允许其它应用程序绑定并且与之交互的Service的实现类。为了提供绑定,必须实现onBind()回调方法。该方法返回IBinder对象(IBinder是接口),它定义了服务类与Activity交互的程序接口。
Activity通过bindService()方法绑定到服务类,同时Activity必须提供ServiceConnection接口的实现类,它监视Activity与服务类之间的连接。在重写ServiceConnection接口的onServiceConnected()方法时,实现了将服务类顺利赋值到了Activity中,实现了在Activity中使用该服务类并执行其中的方法。

1、启动式服务 Started Service的生命周期:
onCreate():创建服务
onStartCommand():服务开始运行(在2.0以前版本中,使用onStart()回调方法)
onDestroy() :服务被停止
【详细说明:】
在程序中调用:context.startService() 会触发执行Service生命周期中的onCreate()、onStartCommand()回调方法,此时服务就开始正式运行;
如果Service还没有运行,则android先调用onCreate()然后调用onStartCommand();如果Service已经运行,则只调用onStartCommand(),所以一个Service的onStartCommand方法可能会重复调用多次;
如果在程序中调用:context.stopService()会触发执行Service生命周期中的onDestroy()回调方法,会让服务停止;
stopService()的时候直接onDestroy,如果是调用者自己直接退出而没有调用stopService()的话,Service会一直在后台运行。该Service的调用者再启动该Service后可以通过stopService关闭Service;stopSelf()
所以StartService的生命周期为:onCreate –> onStartCommand(可多次调用) –> onDestroy。

2、 绑定式服务 Bound Service的生命周期:
onCreate():创建服务
onBind():绑定服务,服务开始运行
onUnbind():取消绑定
onDestroy() :服务被停止
【详细说明:】
在程序中调用:context.bindService()会触发执行Service生命周期中的onCreate()、onBind()回调方法,此时服务开始运行;
onBind将返回给客户端一个IBind接口实例,IBind允许客户端回调服务的方法,比如得到Service运行的状态或其他操作。此后调用者(Context,例如Activity)会和Service绑定在一起;
如果调用Service的调用者Context退出了,那么会依次调用Service生命周期中的onUnbind()、onDestroy()回调方法,会让服务停止;
所以BindService的生命周期为:onCreate –> onBind(只一次,不可多次绑定) –> onUnbind –> onDestory。
【备注:】
Service是不能自己启动的,只有通过 Context 对象调用startService() 和bindService() 方法来启动。
在Service每一次的开启关闭过程中,只有onStartCommand()可被多次调用(通过多次startService调用),其他onCreate()、onBind()、onUnbind()、onDestory()在一个生命周期中只能被调用一次。

Service可以在和多场合的应用中使用,比如播放多媒体的时候用户启动了其他Activity这个时候程序要在后台继续播放,比如检测SD卡上文件的变化,再或者在后台记录你地理信息位置的改变等等,总之服务总是藏在后头的。

IntentService与Service:
不管是何种Service,它默认都是在应用程序的主线程(亦即UI线程)中运行的。所以,如果你的Service将要运行非常耗时或者可能被阻塞的操作时,你的应用程序将会被挂起,甚至会出现ANR错误。为了避免这一问题,你应该在Service中重新启动一个新的线程来进行这些操作。现有两种方法大家参考:
① 直接在Service的onStartCommand()方法中新建一个线程来执行;

② Android SDK 中为我们提供了一个现成的Service类来实现这个功能,它就是IntentService,它主要负责以下几个方面:
Creates a default worker thread that executes all intents delivered to onStartCommand() separate from your application’s main thread.
生成一个默认的且与主线程互相独立的工作者线程来执行所有传送至 onStartCommand() 方法的Intent
Creates a work queue that passes one intent at a time to youronHandleIntent() implementation, so you never have to worry about multi-threading.
生成一个工作队列来传送Intent对象给你的onHandleIntent()方法,同一时刻只传送一个Intent对象,心多线程的问题。这样一来,你就不必担
Stops the service after all start requests have been handled, so you never have to call stopSelf().
在所有的请求(Intent)都被执行完以后会自动停止服务,所以,你不需要自己去调用stopSelf()方法来停止该服务
Provides default implementation of onBind() that returns null.
提供了一个onBind()方法的默认实现,它返回null
Provides a default implementation of onStartCommand() that sends the intent to the work queue and then to your onHandleIntent() implementation
提供了一个onStartCommand()方法的默认实现,它将Intent先传送至工作队列,然后从工作队列中每次取出一个传送至onHandleIntent()方法,在该方法中对Intent对相应的处理

IntentService使用队列的方式将请求的Intent加入队列,然后开启一个worker thread(线程)来处理队列中的Intent,对于异步的startService请求,IntentService会处理完成一个之后再处理第二个,每一个请求都会在一个单独的worker thread中处理,不会阻塞应用程序的主线程。
这里就给我们提供了一个思路,如果有耗时的操作可以在Service里面开启新线程,也可以使用IntentService来处理耗时操作。 但你若是想在Service中让多个线程并发的话,就得使用第一种方法,在Service内部起多个线程,但是这样的话,你可要处理好线程的同步。

0 0
原创粉丝点击