四大组件之Service

来源:互联网 发布:雷洋事件知乎 编辑:程序博客网 时间:2024/05/16 19:39
1 通过startService

    1.1 与调用者相对独立,没有返回,用于播放音乐,下载文件

  1.2 如果是调用者自己直接退出而没有调用stopService的话,Service会一直在后台运行。下次调用者再起来可以stopService。

2 通过bindService

    2.1 与调用者关系密切,有返回,并且可以实现进程间交互。多个组件可以同时与一个Service 绑定,当且仅当所有绑定解除

  2.2 Service只会运行onCreate, 这个时候服务的调用者和服务绑定在一起;调用者退出了,Srevice就会调用onUnbind->onDestroyed所谓绑定在一起就共存亡了。并且这种方式还可以使得调用方(例如)调用服务上的其他的方法。

3、多种方法交织使用

      一个原则是Service的onCreate的方法只会被调用一次,就是你无论多少次的startService又bindService,Service只被创建一次。

      3.1 如果先bind,再start就直接运行onStart方法,同样只能先unbind,再stop;若直接关闭调用者,服务解绑但未停止,停止服务需要通过调用者调用stop。

      3.2 如果先start,再bind就直接运行onBind方法,就stop不掉了,只能先unbind,再stop;若直接关闭调用者,服务同样解绑但未停止,停止服务需要对service调用stop。

      总之,无论是bind+start、还是start+bind,停止服务的方法都要先后调用unbind、stop方法,解绑的方式有两种:一种是调用者主动调用unbind方法,还有一种是关闭调用者完成解绑,但此时想要停止服务,就得在其后对其调用stop方法,当然也可在关闭调用者之前调用stop方法,其后便直接解绑以停止服务。

4、多次调用相关方法

      如果service运行期间调用了bindService,这时候再调用stopService的话,service是不会调用onDestroy方法的,service就stop不掉了,只能调用UnbindService, service就会被销毁

      4.1 如果一个service通过startService 被start之后,多次调用startService 的话,service会多次调用onStart方法。多次调用stopService的话,service只会调用一次onDestroyed方法。

      4.2 如果一个service通过bindService被start之后,多次调用bindService的话,service只会调用一次onBind方法。多次调用unbindService的话会抛出异常。

5、服务在不同调用方法下的生命周期

     服务不能自己运行,需要通过调用Context.startService()或Context.bindService()方法启动服务。

     这两个方法都可以启动Service,但是它们的使用场合有所不同。

      特别指出:

            使用startService()方法启用服务,调用者与服务之间没有关连,即使调用者退出了,服务仍然运行。

            使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止。

6、总结

  如果打算采用Context.startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onStart()方法。如果调用startService()方法前服务已经被创建,多次调用startService()方法并不会导致多次创建服务,但会导致多次调用onStart()方法。采用startService()方法启动的服务,只能调用Context.stopService()方法结束服务,服务结束时会调用onDestroy()方法。
  
  如果打算采用Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onBind()方法。这个时候调用者和服务绑定在一起,调用者退出了,系统就会先调用服务的onUnbind()方法,接着调用onDestroy()方法。如果调用bindService()方法前服务已经被绑定,多次调用bindService()方法并不会导致多次创建服务及绑定(也就是说onCreate()和onBind()方法并不会被多次调用)。如果调用者希望与正在绑定的服务解除绑定,可以调用unbindService()方法,调用该方法也会导致系统调用服务的onUnbind()-->onDestroy()方法.

7、拓展:IntentService

7.1 IntentService官方文档的说明:

  IntentService is a base class for Services that handle asynchronous requests (expressed as Intents) on demand. Clients send requests through startService(Intent) calls; the service is started as needed, handles each Intent in turn using a worker thread, and stops itself when it runs out of work.

  This "work queue processor" pattern is commonly used to offload tasks from an application's main thread. The IntentService class exists to simplify this pattern and take care of the mechanics. To use it, extend IntentService and implement onHandleIntent(Intent). IntentService will receive the Intents, launch a worker thread, and stop the service as appropriate.

  All requests are handled on a single worker thread -- they may take as long as necessary (and will not block the application's main loop), but only one request will be processed at a time.

  翻译过来是:使用队列的方式将请求的Intent加入队列,然后开启一个worker thread(线程)来处理队列中的Intent,对于异步的startService请求,IntentService会处理完成一个之后再处理第二个,每一个请求都会在一个单独的worker thread中处理,不会阻塞应用程序的主线程,这里就给我们提供了一个思路,如果有耗时的操作与其在Service里面开启新线程还不如使用IntentService来处理耗时操作。

  由于服务进程的优先级高于后台进程, 因此如果activity需要执行耗时操作, 最好还是启动一个service来完成. 当然, 在activity中启动子线程完成耗时操作也可以,但是这样做的缺点在于,一旦activity不再可见,activity所在的进程成为后台进程, 而内存不足时后台进程随时都有可能被系统杀死(但是启动service完成耗时操作会带来数据交互的问题, 比如耗时操作需要实时更新UI控件的状态的话,service就不是一个好的选择)。 基于同样的考虑, 在BroadcastReceiver中也不应该执行耗时操作, 而应该启动service来完成(当然, BroadcastReceiver的生命周期过于短暂, 也决定了不能在其中执行耗时操作)。

  IntentService是一个通过Context.startService(Intent)启动可以处理异步请求的Service,使用时你只需要继承IntentService和重写其中的onHandleIntent(Intent)方法接收一个Intent对象,在适当的时候会停止自己(一般在工作完成的时候)。所有的请求的处理都在一个工作线程中完成,它们会交替执行(但不会阻塞主线程的执行),一次只能执行一个请求。

    这是一个基于消息的服务,每次启动该服务并不是马上处理你的工作,而是首先会创建对应的Looper,Handler并且在MessageQueue中添加的附带客户Intent的Message对象,当Looper发现有Message的时候接着得到Intent对象通过在onHandleIntent((Intent)msg.obj)中调用你的处理程序,处理完后即会停止自己的服务,意思是Intent的生命周期跟你的处理的任务是一致的,所以这个类用下载任务中非常好,下载任务结束后服务自身就会结束退出。

7.2 IntentService特征

  IntentService是继承于Service并处理异步请求的一个类,在IntentService内有一个工作线程来处理耗时操作,启动IntentService的方式和启动传统Service一样,同时,当任务执行完后,IntentService会自动停止,而不需要我们去手动控制。另外,可以启动IntentService多次,而每一个耗时操作会以工作队列的方式在IntentService的onHandleIntent回调方法中执行,并且,每次只会执行一个工作线程,执行完第一个再执行第二个,以此类推。

  而且,所有请求都在一个单线程中,不会阻塞应用程序的主线程(UI Thread),同一时间只处理一个请求。

  那么,用IntentService有什么好处呢?

  1. 首先,我们省去了在Service中手动开线程的麻烦,
  2. 第二,当操作完成时,我们不用手动停止Service。

  特征小结:

  1. 会创建独立的worker线程来处理所有的Intent请求;
  2. 会创建独立的worker线程来处理onHandleIntent()方法实现的代码,无需处理多线程问题;
  3. 所有请求处理完成后,IntentService会自动停止,无需调用stopSelf()方法停止Service;

7.3 使用步骤:

  1. 写构造函数
  2. 实现虚函数onHandleIntent,并在里面根据Intent的不同进行不同的事务处理就可以了。
  好处:处理异步请求的时候可以减少写代码的工作量,比较轻松地实现项目的需求
  注意:IntentService的构造函数一定是参数为空的构造函数,然后再在其中调用super("name")这种形式的构造函数。
  因为Service的实例化是系统来完成的,而且系统是用参数为空的构造函数来实例化Service的
  关于Handler和Service的更多知识请阅读《Looper和Handler》,《关于Handler技术》,《Service简介》,《AIDL和Service实现两进程通信》

http://android.tgbus.com/Android/tutorial/201104/347990.shtml

http://www.cnblogs.com/lipeil/archive/2012/08/27/2657880.html

http://www.cnblogs.com/shaweng/p/4024766.html

http://blog.csdn.net/hudashi/article/details/7986130

0 0
原创粉丝点击