- Processes
进程
- Process lifecycle
进程生命周期
- Threads
线程
- Worker threads
工作线程
- Thread-safe
methods 线程安全方法
- Interprocess Communication
进程间通信
进程
- Process lifecycle
进程生命周期
线程
- Worker threads
工作线程 - Thread-safe
methods 线程安全方法
进程间通信
When an application component starts and the application does not have any other components running, the Android system starts a new Linux process for the application with a single thread of execution. By default, all components of the same application run
in the same process and thread (called the "main" thread). If an application component starts and there already exists a process for that application (because another component from the application exists), then the component is started within that process
and uses the same thread of execution. However, you can arrange for different components in your application to run in separate processes, and you can create additional threads for any process.
This document discusses how processes and threads work in an Android application.
当一个应用程序组件启动和运行的应用程序没有任何其他组件,Android系统启动一个新的Linux应用程序的过程用单个线程的执行。默认情况下,同一应用程序的所有组件运行在相同的进程和线程(称为“主要”线程)。如果一个应用程序组件开始,已经存在一个过程,应用程序(因为存在另一个组件从应用程序),那么组件启动过程和使用相同的线程内执行。然而,您可以安排不同的组件在应用程序运行在单独的进程,你可以为任何过程创建额外的线程。
本文讨论了如何在Android应用程序进程和线程的工作。
Processes
By default, all components of the same application run in the same process and most applications should not change this. However, if you find that you need to control which process a certain component belongs to, you can do so in the manifest file.
默认情况下,同一应用程序的所有组件运行在相同的进程,大多数应用程序不应该改变这种情况。然而,如果你发现你需要控制哪些过程属于某一组件,你可以在manifest文件中。
The manifest entry for each type of component element—<activity>
, <service>
, <receiver>
,
and <provider>
—supports an android:process
attribute that can specify a process in which that component
should run. You can set this attribute so that each component runs in its own process or so that some components share a process while others do not. You can also set android:process
so
that components of different applications run in the same process—provided that the applications share the same Linux user ID and are signed with the same certificates.
为每种类型的组件清单条目元素——<活动>,<服务>、<接收机>,和<供应商>支持android:过程属性,可以指定一个组件应该运行的过程。您可以设置该属性,这样每个组件运行在它自己的进程或这样一些组件共享一个过程而其他人没有。设置此属性还可以让不同的应用程序的组件运行在相同的进程中——实现多个应用程序共享相同的Linux用户ID和赋予同样的证书。
The <application>
element also supports an android:process
attribute, to set a default value that
applies to all components.
<应用>元素也支持android:过程属性,设置一个默认值,适用于所有组件。
Android might decide to shut down a process at some point, when memory is low and required by other processes that are more immediately serving the user. Application components running in the process that‘s killed are consequently destroyed. A process is started
again for those components when there‘s again work for them to do.
Android可能决定关闭一个过程在某种程度上,当内存低,要求其他进程,更直接的服务于用户。应用程序组件运行的过程,也会因此被销毁。为这些组件重新开始一个过程的时候再为他们工作。
When deciding which processes to kill, the Android system weighs their relative importance to the user. For example, it more readily shuts down a process hosting activities that are no longer visible on screen, compared to a process hosting visible activities.
The decision whether to terminate a process, therefore, depends on the state of the components running in that process. The rules used to decide which processes to terminate is discussed below.
在决定哪个进程时,Android系统向用户重他们的相对重要性。例如,它更容易关闭托管活动过程不再显示在屏幕上,相比一个托管可见的活动过程。因此,决定是否终止一个进程取决于组件的状态在这一进程运行。终止进程的判定规则用于下面讨论。
Process lifecycle 进程生命周期
The Android system tries to maintain an application process for as long as possible, but eventually needs to remove old processes to reclaim memory for new or more important processes. To determine which processes to keep and which to kill, the system places
each process into an "importance hierarchy" based on the components running in the process and the state of those components. Processes with the lowest importance are eliminated first, then those with the next lowest importance, and so on, as necessary to
recover system resources.
Android系统试图尽可能保持应用程序进程,但最终需要删除旧的进程来回收内存新的或更重要的是过程。来确定哪个进程保留或终止,系统把每个进程都划入一个“重要性层次结构”基于组件中运行过程和这些组件的状态。重要性最低的进程首先是消除,那么下一个最低的重要性,等等,必要时恢复系统资源。
There are five levels in the importance hierarchy. The following list presents the different types of processes in order of importance (the first process is most important and is killed
last):
有五个层次重要性水平。下面的列表给出了不同类型的流程按照重要性(第一个过程是最重要的和被杀最后):
- Foreground process
前台进程
A process that is required for what the user is currently doing. A process is considered to be in the foreground if any of the following conditions are true:
这一过程需要用户目前正在做什么。一个过程被认为是前景如果下列条件:
- It hosts an
Activity
that the user is interacting with (theActivity
‘sonResume()
method
has been called).举办一个活动,用户交互(活动的onResume()方法被调用)。 - It hosts a
Service
that‘s bound to the activity that the user is interacting with. 它所承载的服务绑定到用户交互的活动。 - It hosts a
Service
that‘s running "in the foreground"—the service has calledstartForeground()
.
它的主机服务运行“前景”——服务称为startForeground()。 - It hosts a
Service
that‘s executing one of its lifecycle callbacks (onCreate()
,onStart()
,
oronDestroy()
). 主机的服务的执行它的生命周期回调(onCreate(),onStart(),或onDestroy())。 - It hosts a
BroadcastReceiver
that‘s executing itsonReceive()
method.
它执行主机的BroadcastReceiver onReceive()方法。
Generally, only a few foreground processes exist at any given time. They are killed only as a last resort—if memory is so low that they cannot all continue to run. Generally, at that point, the device has reached a memory paging state, so killing some foreground
processes is required to keep the user interface responsive.一般来说,只有少数前台进程存在在任何给定的时间。它们被杀死只作为最后的策略——当内存不足以维持,他们不能继续运行。一般来说,在这一点上,设备已经达到了一个内存分页状态,所以杀死一些前台进程需要保持用户界面的响应性。
- It hosts an
- Visible process 可视进程
A process that doesn‘t have any foreground components, but still can affect what the user sees on screen. A process is considered to be visible if either of the following conditions are
true:这一过程没有前台组件,但仍然会影响用户在屏幕上看到的内容。一个过程被认为是可见如果下列条件是真实的:
- It hosts an
Activity
that is not in the foreground, but is still visible to the user (itsonPause()
method
has been called). This might occur, for example, if the foreground activity started a dialog, which allows the previous activity to be seen behind it. 举办一个活动,不在前台,但仍可见到用户(onPause()方法被调用)。这可能发生,例如,如果前台活动开始一个对话框,允许它后面看到前面的活动。 - It hosts a
Service
that‘s bound to a visible (or foreground) activity. 主机的服务的绑定到一个可见(或前台)活动。
A visible process is considered extremely important and will not be killed unless doing so is required to keep all foreground processes running.
可见进程被认为是极其重要的,不会被杀死,除非这样做需要维持所有前台进程运行。
- It hosts an
- Service process 服务进程
A process that is running a service that has been started with thestartService()
method and does not fall
into either of the two higher categories. Although service processes are not directly tied to anything the user sees, they are generally doing things that the user cares about (such as playing music in the background or downloading data on the network), so
the system keeps them running unless there‘s not enough memory to retain them along with all foreground and visible processes.这一过程是运行一个服务,由startService()方法已经启动,不落入两个中的哪一个更高的类别。尽管服务过程不直接与用户看到的任何东西,他们通常做用户关心的事情(比如在后台播放音乐或下载数据网络上的),所以系统让他们运行,除非没有足够的内存来留住他们连同所有前景和可见的进程。
- Background process 后台处理
A process holding an activity that‘s not currently visible to the user (the activity‘sonStop()
method has
been called). These processes have no direct impact on the user experience, and the system can kill them at any time to reclaim memory for a foreground, visible, or service process. Usually there are many background processes running, so they are kept in an
LRU (least recently used) list to ensure that the process with the activity that was most recently seen by the user is the last to be killed. If an activity implements its lifecycle methods correctly, and saves its current state, killing its process will not
have a visible effect on the user experience, because when the user navigates back to the activity, the activity restores all of its visible state. See theActivities document for information about saving and restoring state.举行一个活动过程,目前不可见的用户(活动的onStop()方法被调用)。这些过程没有直接影响用户体验,并且系统可以在任何时间来回收内存杀死他们的前景,可见,或服务的过程。通常有很多后台进程运行,所以它们被关在一个LRU(最近最少使用)列表,以确保流程的活动,最近看到的用户是最后被杀死。如果一个活动实现其生命周期方法正确,并保存其当前状态,造成其过程不会有明显影响用户体验,因为当用户导航回活动,活动恢复所有可见的状态。看到无耻文档信息保存和恢复状态。
- Empty process 空进程
A process that doesn‘t hold any active application components. The only reason to keep this kind of process alive is for caching purposes, to improve startup time the next time a component
needs to run in it. The system often kills these processes in order to balance overall system resources between process caches and the underlying kernel caches.这一过程不含任何活动应用程序组件。保持这种过程还活着的唯一原因就是缓存的目的,提高启动时间下次运行组件。系统经常会终止这些进程,以平衡系统整体资源缓存和底层内核缓存之间的过程。
Android ranks a process at the highest level it can, based upon the importance of the components currently active in the process. For example, if a process hosts a service and a visible activity, the process is ranked as a visible process, not a service process.
Android排名最高水平的过程,基于目前活跃组件的重要性。例如,如果一个过程主机一个服务和一个可见的活动,这个过程是列为一个可见的过程,不是一个服务进程。
In addition, a process‘s ranking might be increased because other processes are dependent on it—a process that is serving another process can never be ranked lower than the process it is serving. For example, if a content provider in process A is serving a
client in process B, or if a service in process A is bound to a component in process B, process A is always considered at least as important as process B.
Because a process running a service is ranked higher than a process with background activities, an activity that initiates a long-running operation might do well to start a service for that operation, rather than simply create a worker thread—particularly if
the operation will likely outlast the activity. For example, an activity that‘s uploading a picture to a web site should start a service to perform the upload so that the upload can continue in the background even if the user leaves the activity. Using a service
guarantees that the operation will have at least "service process" priority, regardless of what happens to the activity. This is the same reason that broadcast receivers should employ services rather than simply put time-consuming operations in a thread.
此外,一个进程的级别可能会增加,因为其他进程依赖于这是另一个进程提供服务的过程永远无法排名低于此服务的进程。例如,如果一个内容提供者在处理服务客户机进程B,或如果一个服务进程a是绑定到组件的过程,过程总是认为至少进程B一样重要。
因为流程运行一个服务排名高于与背景活动流程,活动,发起一个长时间运行的操作最好开始一个服务操作,而不是简单地创建一个工人thread-particularly如果操作可能会比活动。例如,一个活动的将照片上传到一个网站应该启动一个服务来执行上传,这样在后台上传可以继续即使用户离开了活动。使用服务保证操作至少都会有“服务流程”优先,不管发生了什么活动。这是同样的原因,广播接收器应该雇佣服务而不是简单地把耗时的操作在一个线程。
Threads 线程
When an application is launched, the system creates a thread of execution for the application, called "main." This thread is very important because it is in charge of dispatching events to the appropriate user interface widgets, including drawing events. It
is also the thread in which your application interacts with components from the Android UI toolkit (components from the
android.widget
and android.view
packages).As such, the main thread is also sometimes called the UI thread.
此外,一个进程的级别可能会增加,因为其他进程依赖于这是另一个进程提供服务的过程永远无法排名低于此服务的进程。例如,如果一个内容提供者在处理服务客户机进程B,或如果一个服务过程是当应用程序启动时,系统会创建一个线程执行的应用程序,称为“主要。“这个线程是非常重要的,因为它负责把事件分发给相应的用户界面小部件,包括屏幕绘图事件。这也是您的应用程序与组件交互的线程从Android
UI toolkit(从android.widget组件和android.view包)。因此,主线程有时也称为UI线程。
The system does not create a separate thread for each instance of a component. All components that run in the same process are instantiated in the UI thread, and system calls to each component are dispatched from
that thread. Consequently, methods that respond to system callbacks (such as onKeyDown()
to report user actions or a lifecycle callback method) always run in the UI thread of
the process.
系统不为每个组件的实例创建一个单独的线程。所有组件运行在同一进程中实例化在UI线程,每个组件和系统调用是派遣的线程。因此,应对系统回调的方法(如onKeyDown()报告用户操作或生命周期回调方法)总是在UI线程的运行过程。
For instance, when the user touches a button on the screen, your app‘s UI thread dispatches the touch event to the widget, which in turn sets its pressed state and posts an invalidate request to the event queue. The UI thread dequeues the request and notifies
the widget that it should redraw itself.
例如,当用户触摸屏幕上的按钮时,应用程序的UI线程分派触摸事件的小部件,进而设置按下和帖子一个无效请求到事件队列。UI线程出列请求和通知小部件应该改变自己。
When your app performs intensive work in response to user interaction, this single thread model can yield poor performance unless you implement your application properly. Specifically, if everything is happening in the UI thread, performing long operations
such as network access or database queries will block the whole UI. When the thread is blocked, no events can be dispatched, including drawing events. From the user‘s perspective, the application appears to hang. Even worse, if the UI thread is blocked for
more than a few seconds (about 5 seconds currently) the user is presented with the infamous "application not
responding" (ANR) dialog. The user might then decide to quit your application and uninstall it if they are unhappy.
当你的应用程序在响应用户交互执行密集的工作,这个单线程模型能产生正常表现不佳,除非您实现您的应用程序。具体地说,如果一切发生在UI线程,耗时很长的操作,如访问网络或数据库查询将会阻塞整个UI。当线程被阻塞,没有事件可以派遣,包括屏幕绘图事件。从用户的角度来看,应用程序挂起。更糟糕的是,如果UI线程被阻塞超过几秒钟目前(大约5秒钟)用户提出了臭名昭著的“应用程序没有响应”(ANR)对话框。用户可能会决定退出你的应用程序和卸载它,如果他们不开心。
Additionally, the Andoid UI toolkit is not thread-safe. So, you must not manipulate your UI from a worker thread—you must do all manipulation to your user interface from the UI thread. Thus, there are simply two
rules to Android‘s single thread model:
此外,Andoid UI工具包不是线程安全的。所以,你不能控制你的UI允许从一个工人操作的用户界面UI线程。因此,仅仅有两个规则,Android的单线程模型:
- Do not block the UI thread 不阻塞UI线程
- Do not access the Android UI toolkit from outside the UI thread 不从外部访问Android UI toolkit UI线程吗
Worker threads 工作线程
Because of the single thread model described above, it‘s vital to the responsiveness of your application‘s UI that you do not block the UI thread. If you have operations to perform that are not instantaneous, you should make sure to do them in separate threads
("background" or "worker" threads).
由于上述单线程模型,应用程序的响应能力是至关重要的UI,你不能阻塞UI线程。如果你有操作执行,不是瞬间,你应该确保他们在单独的线程(“背景”或“工人”线程)。
For example, below is some code for a click listener that downloads an image from a separate thread and displays it in an ImageView
:
例如,下面是一些代码点击监听器,下载一个图像从一个单独的线程在ImageView并显示:
publicvoid onClick(View v){ newThread(newRunnable(){ publicvoid run(){ Bitmap b = loadImageFromNetwork("http://example.com/image.png"); mImageView.setImageBitmap(b); } }).start();}
At first, this seems to work fine, because it creates a new thread to handle the network operation. However, it violates the second rule of the single-threaded model: do not access the Android UI toolkit from outside the
UI thread—this sample modifies the ImageView
from the worker thread instead of the UI thread. This can result in undefined and unexpected behavior, which can be difficult
and time-consuming to track down.
To fix this problem, Android offers several ways to access the UI thread from other threads. Here is a list of methods that can help:
起初,这似乎工作好,因为它创建了一个新线程来处理网络操作。然而,它违反了单线程模型的第二条规则:不要从外部访问Android
UI toolkit UI片样品修改的ImageView工作线程而不是UI线程。这可能导致未定义的和意想不到的行为,可以是困难和耗时的追踪。
为了解决这个问题,Android提供了几种方法来从其他线程访问UI线程。这里是一个列表的方法,可以帮助:
Activity.runOnUiThread(Runnable)
View.post(Runnable)
View.postDelayed(Runnable, long)
For example, you can fix the above code by using the View.post(Runnable)
method:
例如,您可以解决上面的代码通过使用View.post(Runnable)方法:
publicvoid onClick(View v){ newThread(newRunnable(){ publicvoid run(){ finalBitmap bitmap = loadImageFromNetwork("http://example.com/image.png"); mImageView.post(newRunnable(){ publicvoid run(){ mImageView.setImageBitmap(bitmap); } }); } }).start();}
Now this implementation is thread-safe: the network operation is done from a separate thread while theImageView
is manipulated from the UI thread.
现在这个实现线程安全:网络操作完成从一个单独的线程而theImageView操纵从UI线程。
However, as the complexity of the operation grows, this kind of code can get complicated and difficult to maintain. To handle more complex interactions with a worker thread, you might consider using a Handler
in
your worker thread, to process messages delivered from the UI thread. Perhaps the best solution, though, is to extend the AsyncTask
class, which simplifies the execution of worker
thread tasks that need to interact with the UI.
然而,随着操作的复杂性,这种代码也会变得很复杂,很难维护。工作线程来处理更复杂的交互,您可能会考虑使用一个处理程序在工作线程从UI线程处理消息交付。也许最好的解决方案,是扩展AsyncTask类,它简化了工作线程的执行任务,需要与用户界面交互。
Using AsyncTask 使用AsyncTask
AsyncTask
allows you to perform asynchronous work on your user interface. It performs the blocking operations in a worker thread and then publishes the results on the UI thread,
without requiring you to handle threads and/or handlers yourself.
AsyncTask允许您执行异步工作在你的用户界面。它执行阻塞操作在一个工作线程,然后在UI线程上公布结果,不需要你自己处理线程和/或处理程序。
To use it, you must subclass AsyncTask
and implement the doInBackground()
callback method, which
runs in a pool of background threads. To update your UI, you should implement onPostExecute()
, which delivers the result from doInBackground()
and
runs in the UI thread, so you can safely update your UI. You can then run the task by calling execute()
from the UI thread.
使用它,您必须子类AsyncTask,实现doInBackground()回调方法,它运行在一个后台线程池。更新你的UI,你应该实现onPostExecute(),提供来自doInBackground()和结果在UI线程中运行,所以您可以安全地更新UI。然后您可以运行任务从UI线程通过调用execute()。
For example, you can implement the previous example using AsyncTask
this way:
例如,您可以使用AsyncTask实现前面的示例:
publicvoid onClick(View v){ newDownloadImageTask().execute("http://example.com/image.png");} privateclassDownloadImageTaskextendsAsyncTask<String,Void,Bitmap>{ /** The system calls this to perform work in a worker thread and * delivers it the parameters given to AsyncTask.execute() */ protectedBitmap doInBackground(String... urls){ return loadImageFromNetwork(urls[0]); } /** The system calls this to perform work in the UI thread and delivers * the result from doInBackground() */ protectedvoid onPostExecute(Bitmap result){ mImageView.setImageBitmap(result); }}
Now the UI is safe and the code is simpler, because it separates the work into the part that should be done on a worker thread and the part that should be done on the UI thread.
现在UI是安全的,代码比较简单,因为它分离的部分应该完成的工作在一个工作者线程和UI线程上应该做的部分。
You should read the AsyncTask
reference for a full understanding on how to use this class, but here is a quick overview of how it works:
你应该阅读AsyncTask参考充分理解如何使用这个类,但这里是一个快速概述工作原理:
- You can specify the type of the parameters, the progress values, and the final value of the task, using generics 您可以指定的类型参数,进步的价值观,和任务的最终值,使用泛型
- The method
doInBackground()
executes automatically on a worker thread doInBackground()方法执行自动工作线程 onPreExecute()
,onPostExecute()
, andonProgressUpdate()
are
all invoked on the UI threadonPostExecute onPreExecute(),()和onProgressUpdate()都是在UI线程上调用- The value returned by
doInBackground()
is sent toonPostExecute()
doInBackground()返回的值发送到onPostExecute() - You can call
publishProgress()
at anytime indoInBackground()
to
executeonProgressUpdate()
on the UI thread 你可以叫publishProgress()随时doInBackground()来执行onProgressUpdate()在UI线程上 - You can cancel the task at any time, from any thread 你可以在任何时候取消任务,从任何线程
Caution: Another problem you might encounter when using a worker thread is unexpected restarts in your activity due to a runtime configuration change (such as when the user changes the screen orientation), which
may destroy your worker thread. To see how you can persist your task during one of these restarts and how to properly cancel the task when the activity is destroyed, see the source code for the Shelves sample
application.
警告:使用工作线程时您可能会遇到另一个问题是意外重启你的活动由于运行时配置更改(例如,当用户改变屏幕的方向),这可能会毁掉你的工作线程。看看你可以坚持你的任务在其中一个重启和如何正确地取消任务活动被摧毁时,看到货架上的示例应用程序的源代码。
Thread-safe methods
In some situations, the methods you implement might be called from more than one thread, and therefore must be written to be thread-safe.
在某些情况下,这些方法实现可能从多个线程调用,因此必须是线程安全的。
This is primarily true for methods that can be called remotely—such as methods in a bound service. When a call on a method implemented in an IBinder
originates in the same process
in which the IBinder
is running, the method is executed in the caller‘s thread. However, when the call originates in another process, the method is executed in a thread chosen
from a pool of threads that the system maintains in the same process as the IBinder
(it‘s not executed in the UI thread of the process). For example, whereas a service‘s onBind()
method
would be called from the UI thread of the service‘s process, methods implemented in the object that onBind()
returns (for example, a subclass that implements RPC methods) would
be called from threads in the pool. Because a service can have more than one client, more than one pool thread can engage the same IBinder
method at the same time. IBinder
methods
must, therefore, be implemented to be thread-safe.
主要是这样的方法,可以被称为remotely-such绑定服务。当在一个方法的调用实现的一个内部起源于同一进程的内部运行,该方法在调用者的线程中执行。然而,当调用源自另一个进程,一个线程中执行的方法从一个线程池,选择系统保持在同一过程的内部(这不是UI线程的执行过程)。例如,而服务的onBind()方法会从UI线程调用服务的过程中,方法中实现onBind()返回的对象(例如,一个子类实现RPC方法)将从线程池中。因为一个服务可以有多个客户端,可以多个线程池与相同的内部方法在同一时间。因此,IBindermethods必须实现线程安全的。
Similarly, a content provider can receive data requests that originate in other processes. Although theContentResolver
and ContentProvider
classes
hide the details of how the interprocess communication is managed, ContentProvider
methods that respond to those requests—the methods query()
, insert()
, delete()
,update()
,
and getType()
—are called from a pool of threads in the content provider‘s process, not the UI thread for the process. Because these methods might be called from any number of
threads at the same time, they too must be implemented to be thread-safe.
同样,一个内容提供者可以接收来自其他进程的数据请求。尽管theContentResolver和ContentProvider类隐藏进程间通信是如何管理的细节,ContentProvider方法应对那些请求查询(),插入()、删除()、update()和方法()——从一个线程池内容提供者的过程,不是UI线程的过程。因为这些方法可能被称为从任意数量的线程同时,他们也必须实现线程安全的。
Interprocess Communication
Android offers a mechanism for interprocess communication (IPC) using remote procedure calls (RPCs), in which a method is called by an activity or other application component, but executed remotely (in another process), with any result returned back to the
caller. This entails decomposing a method call and its data to a level the operating system can understand, transmitting it from the local process and address space to the remote process and address space, then reassembling and reenacting the call there. Return
values are then transmitted in the opposite direction. Android provides all the code to perform these IPC transactions, so you can focus on defining and implementing the RPC programming interface.
Android提供了进程间通信(IPC)机制使用远程过程调用(rpc),一个方法被调用的一个活动或其他应用程序组件,但执行远程(在另一个进程),与任何结果返回给调用者。这需要分解方法调用和操作系统的数据水平可以理解,从当地的进程和地址空间传输到远程进程和地址空间,然后再组装和执行调用。然后返回值相反的方向传播。Android提供了所有的代码来执行这些IPC事务,这样你就可以专注于定义和实现RPC编程接口。
To perform IPC, your application must bind to a service, using bindService()
. For more information, see theServices developer guide.
执行IPC,应用程序必须绑定到一个服务,使用bindService()。有关更多信息,请参见服务的开发者指南。