【翻译】(11)进程与线程
see
http://developer.android.com/guide/topics/fundamentals/processes-and-threads.html
原文见
http://developer.android.com/guide/topics/fundamentals/processes-and-threads.html
-------------------------------
Processes and Threads
进程与线程
-------------------------------
Quickview
快速概览
* Every application runs in its own process and all components of the application run in that process, by default
* 默认,每个应用程序运行在它自己的进程而应用程序的所有组件运行在该进程。
* Any slow, blocking operations in an activity should be done in a new thread, to avoid slowing down the user interface
* 活动内任何缓慢、阻塞的操作都应用在新线程中进行,以避免拖慢用户界面。
In this document
本文目录
* Processes 进程
* Process lifecycle 进程生命周期
* Threads 线程
* Worker threads 工作者线程
* Thread-safe methods 线程安全的方法
* Interprocess Communication 进程间通信
-------------------------------
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.
当一个应用程序组件启动而该应用程序还没有其它任何组件运行,那么Android系统为这个应用程序启动一个新的带有单一执行线程的Linux进程。默认,相同应用程序的所有组件运行在相同的进程和线程(称为主线程)。如果一个应用程序组件启动而用于那个应用程序的进程已经存在(因为那个应用程序的另一个组件已经存在),那么该组件在那个进程中启动并使用相同的执行线程。然而,你可以安排你的应用程序中的不同组件运行在不同的进程,而且你还可以为任意进程创建附加线程。
This document discusses how processes and threads work in an Android application.
本文讨论进程和线程如何工作在一个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.
默认,相同应用程序的所有组件运行在相同进程,而大多数应用程序不应该改变它。然而,如果你发现你需要控制某个组件属于哪个进程,那么你可以在清单文件中做到这一点。
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.
对于每种组件元素类型的清单条目——<activity>,<service>,<receiver>和<provider>——支持android:process属性,它可以指定组件应该运行在的进程。你可以设置这个属性使每个组件运行在它自己的进程或使一些组件共享一个进程而其它不共享。你还可以设置android:process使不同应用程序的组件运行在相同的进程——假如应用程序共享相同的Linux用户ID并签有相同的证书。
The <application> element also supports an android:process attribute, to set a default value that applies to all components.
<application>元素还支持android:process属性,以设置应用到所有组件的默认值。
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):
在重要度等级中有五级。以下列表以重要程度的次序给出不同类型的进程(第一种进程最重要,最后才被杀死):
1. Foreground process
1. 前台进程
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 (the Activity's onResume() method has been called).
* 它持有用户正在交互的Activity对象(Activity的onResume()方法已经被调用)。
* It hosts a Service that's bound to the activity that the user is interacting with.
* 它持有用户正在交互的绑定到活动的Service对象。
* It hosts a Service that's running "in the foreground"—the service has called startForeground().
* 它持有正在运行“在前台”的服务——服务已经调用了startForeground()。
* It hosts a Service that's executing one of its lifecycle callbacks (onCreate(), onStart(), or onDestroy()).
* 它持有正在执行它的其中一个生命周期活动(onCreate(),onStart()或onDestroy())的Service对象。
* It hosts a BroadcastReceiver that's executing its onReceive() method.
* 它持有正在执行它的onReceive()方法的BroadcastReceiver对象。
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.
通常,在任意给定的时刻,只有一些前台进程存在。它们不得已才会被杀死——如果内存太低以致它们所有都不能继续运行,在这种情况下,设备已经达到内存分页状态(注:这里memory paging可能是指虚拟内存机制需要把数据从主存传输到其它存储介质上,也可能指内存的重新分配),所以需要杀死一些前台进程以维持用户界面的响应。
2. Visible process
2. 可见进程
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 (its onPause() 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.
* 它持有不在前台的Activity对象,但仍然对于用户是可见(它的onPause()方法已经被调用)。这可能会发生,例如,如果前台活动启动一个对话框,它允许前一个活动在它后面被看到。
* It hosts a Service that's bound to a visible (or foreground) activity.
* 它持有绑定到可见(或前台)活动的Service对象。
A visible process is considered extremely important and will not be killed unless doing so is required to keep all foreground processes running.
一个可见进程被认为是非常重要的,将不会被杀死,除非需要这样做来保持所有前台进程的运行。
3. Service process
3. 服务进程
A process that is running a service that has been started with the startService() 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()方法启动的服务,并且不会划分到两个更高分类之中的其中一个。尽管服务进程不会直接地关联到用户看到的任何东西上,然而它们通常做用户关注的事情(诸如在后台播放音乐或下载网络上的数据),所以系统让它们持续运行,除非没有足够内存保留它们与所有前台和可见的进程在一起。
4. Background process
4. 后台进程
A process holding an activity that's not currently visible to the user (the activity's onStop() 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 the Activities document for information about saving and restoring state.
一种进程,持有当前对于用户不可见的活动(活动的onStop()方法已经被调用)。这些进程对于用户体验没有直接的冲击,而系统可以在任何时刻杀死它们以回收内存给前台、可见或服务进程。通常有很多后台进程在运行,所以它们被保存在一个LRU(最近最少使用)(注:一种缓存算法,舍弃最近用得最少的条目,保留最近使用的条目)列表以确保带有最近被用户看到的活动的进程最后才被杀死。如果一个活动正确地实现它的活动生命周期方法,而且保存它的当前状态,那么杀死它的进程将不会对用户体验产生可见的效果,因为当用户导航回退到活动时,活动恢复它的所有可见状态。参见活动文档以获取关于保存与恢复状态的信息。
5. Empty process
5. 空进程
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.
另外,一个进程的排行可能由于其它进程依赖于它而被提高——一个服务于其它进程的进程从不会被排列低于它正在服务的进程。例如,如果进程A中的一个内容提供者正在服务进程B中的一个客户端,或者如果进程A中的一个服务被绑定到进程B中的一个组件,那么进程A总是被认为至少要和进程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.
因为运行一个服务的进程被排序高于带有后台活动的进程,那么初始化一个长期运行的操作的活动可能最好启动服务来做那个操作,而不是简单地创建一个工作者线程——特别地,如果那个操作可能把活动拖延很久。例如,一个上传图片到网站的活动将启动一个服务去执行上传动作,使上传可以在后台继续,即便用户离开了活动。使用服务可以保证操作至少拥有“服务进程”的优先级,不管活动发生什么事情。由于相同的原因,广播接收器应该使用服务而非简单地把消耗时间的操作放在一个线程中。
-------------------------------
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.
当一个应用程序被启动时,系统为应用程序创建一个执行线程,称为主线程。这个线程非常重要,因为它负责派发事件给合适的用户界面部件,包括绘画事件。它还是你的应用程序与来自Android用户界面工具箱的组件(来自android.widget和android.view包的组件)交互的线程。因此,主线程有时还被称为用户界面线程。
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.
系统不创建单独的线程给每个组件实例。所有运行在同一进程的组件在用户界面线程中被实例化,对每个组件的系统调用都是从那个线程中派发出去的。因此,响应系统回调的方法(诸如报告用户动作的onKeyDown()或一个生命周期活动方法)总是运行在进程的用户界面线程中。
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.
例如,当用户触碰屏幕上的一个按钮时,你的应用程序的用户界面线程派发触碰事件给部件,它依次设置它的按下状态并派发一个不可用(注:这里invalidate指屏幕不可用,要求刷新整个屏幕的内容)请求给事件队列。用户界面线程把请求出列并通知部件它将重画自己。
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.
当你的应用程序执行密集工作以响应用户界面时,单线程模型可能产生较差的性能,除非你合理地实现你的应用程序。特别地,如果任何事情都发生在用户界面线程中,那么执行长期操作诸如网络访问或数据库查询将阻塞整个用户界面。当线程被阻塞,没有事件可以被派发,包括绘画事件。从用户的视觉看,应用程序显得被挂起。更坏的是,如果用户界面线程被阻塞超过数秒(当前大概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:
另外,Android用户界面工具箱不是线程安全的。所以,你不允许从一个工作者线程中操纵你的用户界面——你必须从用户界面线程中执行对你的用户界面的所有操纵。因此,简单来说,对于Android单线程模型有两个规则:
1. Do not block the UI thread
1. 不要阻塞用户界面线程
2. Do not access the Android UI toolkit from outside the UI thread
2. 不要从用户界面线程外访问Android用户界面工具箱
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).
由于上面描述的单线程模型,所以你不阻塞用户界面线程对于你的应用程序用户界面的响应十分重要。如果你要执行的操作不是瞬间的,那么你应该确保在单独的线程(“后台”或“工作者”线程)中完成它们。
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中显示它。
-------------------------------
public void onClick(View v) {
new Thread(new Runnable() {
public void 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.
首先,这似乎工作良好,因为它创建一个新线程处理网络操作。然而,它违反了单线程模型的第二条规则:不可以从用户界面线程外部访问Android用户界面工具箱——这个示例从工作者线程中修改ImageView而非用户界面线程。这可能导致未定义和不可预期的行为,跟踪这种错误可能困难而且浪费时间。
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提供从其它线程访问用户界面线程的几种方式。这里有一个可能有用的方法列表:
* 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)方法修正上面的代码:
-------------------------------
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
final Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png");
mImageView.post(new Runnable() {
public void run() {
mImageView.setImageBitmap(bitmap);
}
});
}
}).start();
}
-------------------------------
Now this implementation is thread-safe: the network operation is done from a separate thread while the ImageView is manipulated from the UI thread.
现在这个实现是线程安全的:网络操作被单独的线程完成,而ImageView被用户界面线程操纵。
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.
然而,因为操作增长的复杂性,这类代码可能变得复杂和难于维护。为了处理与工作者线程更复杂的交互,你可以考虑在你的工作者线程中使用Handler,以处理从用户界面线程传递过来的消息。尽管如此,可能最好的解决方案是扩展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允许你在你的用户界面上执行异步工作。它在工作者线程上执行阻塞操作然后发布其结果到用户界面线程,不需要你自己处理线程和/或句柄。
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()回调方法,它运行在后台线程池中。为了更新你的用户界面,你应该实现onPostExecute(),它传递来自doInBackground()的结果并且运行在用户界面线程中,所以你可以安全地更新你的用户界面。然后你可以通过从用户界面线程调用execute()来运行任务。
For example, you can implement the previous example using AsyncTask this way:
例如,你可以用这种AsyncTask的方法实现前面的示例:
-------------------------------
public void onClick(View v) {
new DownloadImageTask().execute("http://example.com/image.png");
}
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
/** The system calls this to perform work in a worker thread and
* delivers it the parameters given to AsyncTask.execute() */
/** 系统调用这个方法执行工作线程中的工作并且
* 把传给AsyncTask.execute()的参数传递给它 */
protected Bitmap doInBackground(String... urls) {
return loadImageFromNetwork(urls[0]);
}
/** The system calls this to perform work in the UI thread and delivers
* the result from doInBackground() */
/** 系统调用这个方法执行用户界面线程中的工作并且
* 传递来自doInBackground()的结果 */
protected void 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.
现在用户界面是安全的而且代码更简单,因为它把工作分割成部分应该在工作者线程上完成,部分应该在用户界面线程上完成。
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(), and onProgressUpdate() are all invoked on the UI thread
* onPreExecute(),onPostExecute()和onProgressUpdate()全都在用户界面线程上被调用。
* The value returned by doInBackground() is sent to onPostExecute()
* doInBackground()返回的值被发送到onPostExecute()
* You can call publishProgress() at anytime in doInBackground() to execute onProgressUpdate() on the UI thread
* 你可以在doInBackground()中任意时刻调用publishProgress()以在用户线程上执行onProgressUpdate()
* 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.
警告:当使用一个线程时你可能遇到的另一个问题是在你的活动中由于运行期配置的改变导致不可预期的重启(诸如当用户改变屏幕方向),它可能破坏你的工作者线程。为了知道你如何可以在这些重启的其中一次的期间维持你的任务,以及如何在活动被销毁时合理地取消任务,请参见Shelves(注:一个Android书架管理应用程序,项目主页在http://code.google.com/p/shelves/)示例应用程序的源代码。
-------------------------------
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.
这首先对于可以被远程调用的方法来说是正确的——诸如在一个被绑定的服务中的方法。当对一个在IBinder中实现的方法的调用来源于与IBinder正在运行的相同进程时,该方法在调用方的线程中被执行。然而,当调用起源于另一个进程,那么方法被调用在线程池中的一个线程中,系统维护它在与IBinder相同的进程中(它不在进程的用户界面线程中执行)。例如,虽然一个服务的onBind()方法将被服务进程的用户界面线程调用,但是在onBind()返回对象(例如,一个实现RPC方法的子类)中实现的方法将被池中的线程调用。因为一个服务可以拥有多于一个客户端,所以在相同时刻可以有多于一个池的线程参与相同的IBinder方法。因此,IBinder方法必须实现为线程安全。
Similarly, a content provider can receive data requests that originate in other processes. Although the ContentResolver 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.
类似地,一个内容提供者可以接收来源于其它进程的数据请求。虽然ContentResolver和ContentProvider类隐藏了进程间通信是如何被管理的细节,然而ContentProvider的响应那些请求的方法——方法query(),insert(),delete(),update()和getType()——从内容提供者的进程内的线程池中被调用,而非进程的用户界面线程。因为这些方法可能同时被任意数量的线程调用,所以它们还必须实现为线程安全。
-------------------------------
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 the Services developer guide.
为了执行IPC,你的应用程序必须使用bindService()绑定到一个服务。想获取更多信息,请参见服务开发者指引。
Except as noted, this content is licensed under Apache 2.0. For details and restrictions, see the Content License.
除特别说明外,本文在Apache 2.0下许可。细节和限制请参考内容许可证。
Android 4.0 r1 - 11 Nov 2011 21:02
-------------------------------
Portions of this page are modifications based on work created and shared by the Android Open Source Project and used according to terms described in the Creative Commons 2.5 Attribution License.
(此页部分内容基于Android开源项目,以及使用根据创作公共2.5来源许可证描述的条款进行修改)