我目前正在使用alarmmanager来启动一个服务,以便将位置信息发送到http。问题是当管理器启动并运行服务时,界面似乎会停止一段时间。我想问一下服务线程是否与UI线程分离?
我目前正在使用alarmmanager来启动一个服务,以便将位置信息发送到http。问题是当管理器启动并运行服务时,界面似乎会停止一段时间。我想问一下服务线程是否与UI线程分离?
需要澄清的是:应用程序的主线程并不总是UI线程。
例如:如果一个活动被停止,onStop()会被调用,因此UI线程会从该活动中移开,并移到同一应用程序或不同应用程序中的另一个活动中。
然而,这并不意味着该应用程序不再活动。此外,如果后台运行着一个(已启动的)服务,它可能会继续运行一段时间,直到终止或Android操作系统由于资源不足而终止它。
在这段时间里,谁在运行这个服务?谁触发了onStop()或onDestroy()?这是由应用程序的主线程完成的。
UI线程是一种单例模式,每次只能由一个可见活动使用。应用程序的主线程要么加入/附加到UI线程,要么另一个线程获取它。然而,这并不意味着应用程序没有自己的主线程。
这种行为来自于Android系统基于Linux / Unix的基础知识。大多数开发人员不知道的是:应用程序是Linux / Unix操作系统中的“用户”。
每当调用应用程序时,就类似于用户登录到系统中。在应用程序的情况下,用户ID是唯一的应用程序ID,而不需要密码。新登录的“用户”(即Android应用程序)会获得一个进程和资源,例如Java虚拟机的实例。该进程专门用于此用户,资源包括文件系统配额、文件描述符和处理器允许它与操作系统通信。
Android应用程序的主线程是从Android操作系统交给该应用程序的进程创建的根线程。在该应用程序中创建的任何新线程都将始终返回到主线程。
应用程序的主线程可以访问的系统资源之一是UI线程。因此,应用程序可以请求主线程,但请求可能会被拒绝(或授权)。例如:如果应用程序进程超过其允许的内存分配大小,Android操作系统可能会拒绝访问UI线程并甚至销毁应用程序并终止该进程。
通过在AndroidManifest.xml中定义,可以为一个应用程序(Unix进程分支)定义多个进程。但请注意,分配给每个进程的资源将不同,即每个进程都将有自己的VM,因此在不同进程中维护的对象将无法通过相同的JVM堆共享信息。
从Android文档中复制:
注意:服务在其托管进程的主线程中运行——服务不创建自己的线程,也不在单独的进程中运行(除非您另外指定)。这意味着,如果您的服务将执行任何CPU密集型工作或阻塞操作(例如MP3播放或网络),您应该在服务内部创建一个新线程来执行该工作。通过使用单独的线程,您将减少应用程序未响应(ANR)错误的风险,并且应用程序的主线程可以保持专用于与活动的用户交互。
如果您不想自己管理线程,请使用IntentService
。或者使用AsyncTasks
。
来自安卓开发者:
什么是Service?
关于Service类,大多数人的困惑实际上都是围绕着它不是什么而产生的:
Service不是一个独立的进程。Service对象本身并不意味着它在自己的进程中运行;除非另有说明,否则它将在与其所属的应用程序相同的进程中运行。 Service不是一个线程。它本身不是在主线程之外执行工作的方式(以避免应用程序无响应错误)。 因此,Service本身实际上非常简单,提供了两个主要功能:
一种机制,让应用程序告诉系统它想要在后台做什么(即使用户没有直接与应用程序交互)。这对应于对Context.startService()的调用,它要求系统为服务安排工作,直到服务或其他人明确地停止它。 一种机制,让应用程序向其他应用程序公开一些功能。这对应于对Context.bindService()的调用,它允许建立长期连接以与服务进行交互。 当Service组件实际上被创建时,出于这两个原因之一,系统实际上所做的就是实例化组件并在主线程上调用其onCreate()和任何其他适当的回调。由Service来实现这些行为,例如在其中创建一个次要线程来执行其工作。
请注意,由于Service本身非常简单,因此您可以将与其交互的方式简单或复杂地处理:从将其视为本地Java对象,您可以直接调用其方法(如Local Service示例所示),到使用AIDL提供完整的可远程接口。