本菜鸟最近被android的Service搞昏了头,今天上官网查了文档,特将新的记录与此。下面是官方文档对Service的解析。
A Service
is an application component that can perform long-running operations in the background and does not provide a user interface. Another application component can start a service and it will continue to run in the background even if the user switches to another application. Additionally, a component can bind to a service to interact with it and even perform interprocess communication (IPC). For example, a service might handle network transactions, play music, perform file I/O, or interact with a content provider, all from the background.
A service can essentially take two forms:
-
Started
-
A service is "started" when an application component (such as an activity) starts it by calling
startService()
. Once started, a service can run in the background indefinitely, even if the component that started it is destroyed. Usually,a started service performs a single operation and does not return a result to the caller.For example, it might download or upload a file over the network. When the operation is done, the service should stop itself.
Bound
-
A service is "bound" when an application component binds to it by calling
bindService()
. A bound service offers a client-server interface that allows components to interact with the service, send requests, get results, and even do so across processes with interprocess communication (IPC). A bound service runs only as long as another application component is bound to it. Multiple components can bind to the service at once,but when all of them unbind, the service is destroyed.
服务可以是一个android应用的组成部分,服务可以一直在后台运行并且不提供任何的UI接口。一个android应用中其他组件(例如一个activity)可以启动一个服务,那么这个服务可以一直在后台运行,甚至是切换到了其他的应用。另外,一个组件还以绑定一个服务,甚至可以通过IPC机制进行通行(组件/服务,通信).......
服务主要存在一下两种形式:
1,startService()
当应用的某个组件(例如activity)调用startService()函数的时候。服务一旦启动,该服务可以在后台运行,甚至是启动这个服务的app destroy了,也不会影响该服务。通常服务用来处理单一操作,并且不会有返回值给caller。例如,服务可能是通过网络上传或者下载一些文件,当这些操作完成以后,该服务需要自行终止。
2 , Bound
当应用的组件调用bindService()时,一个服务就被绑定给了一个应用。一个绑定的服务提供一个C/S接口让绑定该服务的组件和服务交互。一个绑定的服务在,unbound()之后就会销毁,而且多个组件可以绑定同一个服务,在最后一个组件unbound这个服务的时候,该服务就会销毁。
Caution: A service runs in the main thread of its hosting process—the service does not create its own thread and does not run in a separate process (unless you specify otherwise). This means that, if your service is going to do any CPU intensive work or blocking operations (such as MP3playback or networking), you should create a new thread within the service to do that work. By using a separate thread, you will reduce the risk of Application Not Responding (ANR) errors and the application's main thread can remain dedicated to user interaction with your activities.
关于服务之前存在一些误解,任务服务会是当前UI线程的一个主先前,看了上面的Caution才发现自己好傻。
注意:服务运行在android应用的主线程内,也就是UI线程内。服务并不会创建自己的线程,或者运行在其他的进程当中(除非自己开个进程给服务)。这意味着,如果这个服务会做一些比较费CPU或者阻塞操作,那么我们就应该创建一个新线程然或再做这些操作。使用这种创建新线程的方法,可以避免ANR异常。而且应用主线程即UI线程可以维持对UI交互的响应。
自己之所以会翻译上面的内容,源于最近修改的一个bug。最近在维护一个应用(CMMB)。这个应用在启动的时候会开启一个服务MBBMSService,这个时候会调用MBBMSService的onCreate()函数, 在该服务的onCreate中会进行一些费时和阻塞操作。这个时候应该在启动这个服务的时候,开启一个线程在处理服务启动后需要具体做的操作。
然而,在应用退出后,要停掉该服务,调用stopService()---》MBBMSService的onDestroy()函数,在onDestroy()函数中,同样会进行一些耗时/阻塞操作。这个时候,主线程被block了,之后就anr了。一直不明白为什么推出服务的时候就起一个线程呢?为什么,一定要等服务退出之后,再继续推出应用呢?按照官方文档的说法,服务启动之后,即使启动它的组件推出了,也不会有影响。
那么这个设计的原因会不会是因为,如果开启一个线程去stopService,那样可能会出现这样一种情况,应用已经完全推出了,而服务还没有完全推出,这个时候会不会挂?还有研究啊~~~
我们的解决方法就是,在stopService的时候开一个线程来执行具体操作。就目前看还好,以后会不会出问题呢?希望android大牛们赐教。