Android applications are written in the Java programming language. The compiled Java code — along with any data and resource files required by the application — is bundled by the aapt
tool into an Android package, an archive file marked by an .apk
suffix. This file is the vehicle for distributing the application and installing it on mobile devices; it's the file users download to their devices. All the code in a single .apk
file is considered to be one application.
Android應用程序是用Java編程語言編寫的。編譯好的Java代碼——隨同所有應用程序要使用的數據和資源文件一塊兒——使用aapt
tool打包成一個Android包,即一個後綴爲.apk
的歸檔文件。此文件是公佈應用程序和在移動設備上安裝應用程序的有媒介;它是用戶下載到他們設備上的文件。在一個.apk文件裏的所有代碼被以爲是一個應用程序。
html
In many ways, each Android application lives in its own world:
從很是多方面來說。每一個Android程序都執行在本身的空間裏:
java
Android在應用程序中某段代碼需要被執行時啓動一個進程,再也不使用或系統資源被其它應用程序請求時關閉這個進程。
react
It's possible to arrange for two applications to share the same user ID, in which case they will be able to see each other's files. To conserve system resources, applications with the same ID can also arrange to run in the same Linux process, sharing the same VM.
可以爲兩個應用程序安排爲使用同一個用戶ID,這樣,他們的文件相互可見。爲爲了節省系統資源。擁有一樣ID的程序可以做爲一個Linux進程執行,分享同一個虛擬機。
android
A central feature of Android is that one application can make use of elements of other applications (provided those applications permit it). For example, if your application needs to display a scrolling list of images and another application has developed a suitable scroller and made it available to others, you can call upon that scroller to do the work, rather than develop your own. Your application doesn't incorporate the code of the other application or link to it. Rather, it simply starts up that piece of the other application when the need arises.
Android的一箇中心功能就是應用程序可以使用其它應用程序的元素(在提供元素的應用程序贊成的狀況下)。好比,假設您的應用程序想要顯示一系列帶有滑屏效果功能的圖片,而後某個應用程序正巧開發出了合適的滑屏的模塊。而且贊成共享。您就可以調用哪一個滑屏模塊處理這些圖片並顯示出來。而不是您本身再去開發一個。您的應用程序並無包括或連接到了其它的應用程序的代碼。但是當請求發出後,您的應用程序確實可以簡單的使用其它程序的部分功能。
ios
For this to work, the system must be able to start an application process when any part of it is needed, and instantiate the Java objects for that part. Therefore, unlike applications on most other systems, Android applications don't have a single entry point for everything in the application (no main()
function, for example). Rather, they have essentialcomponents that the system can instantiate and run as needed. There are four types of components:
爲了達成這個過程。系統必須可以再應用程序的某個部分被請求時啓動這個程序的進程。而後爲那個部分的Java對象建立實例。web
所以不像其它操做系統上的應用程序那樣,Android程序沒有一個單一的應用程序入口(好比沒有main()
函數)。然而他們含有當系統需要時建立實例的實質的組件。數據庫
組件有四種:編程
Activity
base class.
好比。活動會顯示一個用戶可選的菜單項的列表。或是顯示帶有標籤的照片。一個文本信息應用程序可能有一個顯示聯繫人列表來發送信息。又有一個爲選定的聯繫人撰寫信息的活動,還有其它回想舊信息或改變設定的活動。windows
儘管他們整體組成一個相互關聯的用戶界面,但是每一個活動都是相對獨立的。每一個都做爲Activity基類的一個子類來實現。緩存
An application might consist of just one activity or, like the text messaging application just mentioned, it may contain several. What the activities are, and how many there are depends, of course, on the application and its design. Typically, one of the activities is marked as the first one that should be presented to the user when the application is launched. Moving from one activity to another is accomplished by having the current activity start the next one.
一個應用程序可能僅僅含有一個活動,或者像上邊提到的文本信息程序同樣含有幾個。
有幾個活動,這些活動是什麼樣的取決於您的應用程序是怎樣設計的。
最典型的是將一個活動設計爲第一個活動,應用程序被載入時呈現給用戶。從一個活動轉到還有一個是經過在當前活動開始還有一個來實現的。
Each activity is given a default window to draw in. Typically, the window fills the screen, but it might be smaller than the screen and float on top of other windows. An activity can also make use of additional windows — for example, a pop-up dialog that calls for a user response in the midst of the activity, or a window that presents users with vital information when they select a particular item on-screen.
每一個活動提供了一個用以繪製的默認窗體。典型的,窗體填滿整個屏幕,但是它覆蓋在其它窗體上時,會變得略小一點。一個活動可以使用多個窗體——好比,在窗體中央顯示一個需要用戶迴應的彈出窗體,或者在用戶選擇屏幕上一個特定項目是時爲他顯示重要信息的窗體。
The visual content of the window is provided by a hierarchy of views — objects derived from the base View
class. Each view controls a particular rectangular space within the window. Parent views contain and organize the layout of their children. Leaf views (those at the bottom of the hierarchy) draw in the rectangles they control and respond to user actions directed at that space. Thus, views are where the activity's interaction with the user takes place. For example, a view might display a small image and initiate an action when the user taps that image. Android has a number of ready-made views that you can use — including buttons, text fields, scroll bars, menu items, check boxes, and more.
窗體的可見內容由一組view層提供——從View基類衍生出來的對象。每一個view控制窗體中的一塊矩形區域。父view包括並組織子view的佈局。
頁view(底層的view)繪製它們管理的矩形,並響應在「空白」的地方的動做。就是說。view就是活動和用戶互動的地方。好比,一個view顯示一個小圖片,而後初始化用戶點擊這個小圖片後的動做。
Android有很是多已作好的view供您選擇——包括按鈕,文本輸入框。滾動欄,菜單項。多選列表等。
A view hierarchy is placed within an activity's window by the
method. The content view is the View object at the root of the hierarchy. (See the separate User Interface document for more information on views and the hierarchy.)Activity.setContentView()
Activity.setContentView()方法將一組view層放置在一個活動的窗體中。
content view是在層的最底部的View對象。(參見獨立User Interface的文檔獲取不少其它有關view和層的信息。)
Service
base class.
Service基類繼承來的。
A prime example is a media player playing songs from a play list. The player application would probably have one or more activities that allow the user to choose songs and start playing them. However, the music playback itself would not be handled by an activity because users will expect the music to keep playing even after they leave the player and begin something different. To keep the music going, the media player activity could start a service to run in the background. The system would then keep the music playback service running even after the activity that started it leaves the screen.
一個基本的樣例就是一個從列表中播放音樂的媒體播放器。播放器程序可能會有一個或幾個贊成用戶選擇但願播放的音樂而後顯示播放的活動。
但是音樂的回放過程自己不會使用一個活動因爲用戶但願在切出播放器界面作別的事時音樂也能一直放下去。爲了保持播放繼續,活動可以啓動一個服務在後臺執行。
而後即便啓動這個服務的活動退出,音樂播放服務也能繼續執行。
It's possible to connect to (bind to) an ongoing service (and start the service if it's not already running). While connected, you can communicate with the service through an interface that the service exposes. For the music service, this interface might allow users to pause, rewind, stop, and restart the playback.
您可以鏈接到(綁定到)一個正在執行的服務(若果服務沒在執行,就會啓動這個服務)。鏈接後,您就可以經過服務暴露出來的接口與其進行通訊。對音樂播放服務,這個接口可能贊成用戶對播放進行暫停、回退、中止、重播等操做。
Like activities and the other components, services run in the main thread of the application process. So that they won't block other components or the user interface, they often spawn another thread for time-consuming tasks (like music playback). See Processes and Threads, later.
這樣它們就不會阻礙其它組件或是用戶界面,它們通常是執行一個子線程來進行實時的任務(好比音樂回放)。
事後請參見Processes and Threads。
多數的廣播是由系統代碼發出的——好比,時區變化的通知、電量低的通知、照了一張照了一張照片 或者用戶改變了語言設定。應用程序也可以初始化一條廣播——好比讓其它應用程序知道有些數據下載完畢可以使用難過了。
An application can have any number of broadcast receivers to respond to any announcements it considers important. All receivers extend the BroadcastReceiver
base class.
應用程序可以含有隨意數量的廣播接收器對隨意其以爲重要的的廣播進行響應。所有的廣播接收器均由BroadcastReceiver基類衍生
Broadcast receivers do not display a user interface. However, they may start an activity in response to the information they receive, or they may use the BroadcastReceiver to alert the user. Notifications can get the user's attention in various ways — flashing the backlight, vibrating the device, playing a sound, and so on. They typically place a persistent icon in the status bar, which users can open to get the message.
BroadcastReceiver來通知警告用戶。
Notification(通知)可以一各類方式引發用戶注意——使背景燈閃爍。使設備振動,播放聲音等等。
通常是在狀態條上顯示一個不會消失圖標,用戶可以拉下狀態條得到通知。
ContentProvider
base class to implement a standard set of methods that enable other applications to retrieve and store data of the type it controls. However, applications do not call these methods directly. Rather they use a
ContentResolver
object and call its methods instead. A ContentResolver can talk to any content provider; it cooperates with the provider to manage any interprocess communication that's involved.
ContentProvider基類派生。實現了一系列的 使其它程序獲取和存儲其支持的數據格式的 方法。
但是應用程序不會直接調用這些方法。而是使用ContentResolver對象,而後調用這個對象的方法。ContentResolver能與不論什麼內容提供者對話,它與提供者合做來管理所有涉及到的進程間通訊。
See the separate Content Providers document for more information on using content providers.
Whenever there's a request that should be handled by a particular component, Android makes sure that the application process of the component is running, starting it if necessary, and that an appropriate instance of the component is available, creating the instance if necessary.
當有應被特殊的組件操做的請求時,Android會確認這個組件是否正在執行,假設未在執行,則啓動它。假設正在執行則檢測需要的類是否實例化。如未實例化,則爲類建立實例。
Content providers are activated when they're targeted by a request from a ContentResolver. The other three components — activities, services, and broadcast receivers — are activated by asynchronous messages called intents. An intent is an Intent
object that holds the content of the message. For activities and services, it names the action being requested and specifies the URI of the data to act on, among other things. For example, it might convey a request for an activity to present an image to the user or let the user edit some text. For broadcast receivers, the Intent object names the action being announced. For example, it might announce to interested parties that the camera button has been pressed.
內容提供者得到ContentResolver請求的指向後,會被激活。另外的三種組件——活動。服務,廣播接收器——是靠異一種叫作intents(意圖)的異步消息激活的。
意圖是 承載了這樣的異步消息內容的 Intent
的對象。
對於活動和服務。它主要是爲被請求的動做命名。而後指定操做此數據的URI。好比,它可能攜帶讓一個活動爲用戶展示一張圖片或者讓用戶編輯文本的請求。
對廣播接收器,Intent對象爲將要廣播的內容命名。
好比。它可能會向有興趣的接收器公佈照相鍵被按下的廣播。
There are separate methods for activiating each type of component:
激活不一樣的組件需使用不一樣的方法:
Context.startActivity()
or Activity.startActivityForResult()
. The responding activity can look at the initial intent that caused it to be launched by calling its getIntent()
method. Android calls the activity's onNewIntent()
method to pass it any subsequent intents. 向
Context.startActivity()或
Activity.startActivityForResult()傳遞Intent對象可以激活(或得到新的任務)一個活動。響應的活動可以經過調用
getIntent()方法查看致使本身被激活的最初的意圖。Android調用活動的
onNewIntent()方法來傳遞以後的意圖。One activity often starts the next one. If it expects a result back from the activity it's starting, it calls startActivityForResult()
instead of startActivity()
. For example, if it starts an activity that lets the user pick a photo, it might expect to be returned the chosen photo. The result is returned in an Intent object that's passed to the calling activity's
method. 一個活動通常會開啓還有一個活動。假設前一個活動但願重新啓動的活動得到一個執行結果,可以調用onActivityResult()
startActivityForResult()
方法來取代startActivity()
方法。好比。假設一個老活動開啓了一個讓用戶照相的新活動。又但願重新活動得到這張照片。
新活動的執行結果是經過一個 傳遞給老活動的
onActivityResult()方法的 Intent對象傳遞的。
A service is started (or new instructions are given to an ongoing service) by passing an Intent object to
. Android calls the service's Context.startService()
method and passes it the Intent object.onStart()
Similarly, an intent can be passed to
to establish an ongoing connection between the calling component and a target service. The service receives the Intent object in an Context.bindService()
call. (If the service is not already running, onBind()
bindService()
can optionally start it.) For example, an activity might establish a connection with the music playback service mentioned earlier so that it can provide the user with the means (a user interface) for controlling the playback. The activity would call bindService()
to set up that connection, and then call methods defined by the service to affect the playback. 服務經過向
Context.startService()傳遞一個Intent對象啓動(或給予新任務)Android調用服務的
onStart()方法而後將Intent對象傳遞給服務。類似的,一個意圖可以被傳給
Context.bindService()來創建呼叫組件和被叫組件的實時鏈接。調用服務的
onBind()來使其接受Intent對象。(假設服務未在執行。您可以選擇使用bindService()
來啓動它。)好比上面提到過的音樂播放服務,活動會但願創建一個與此服務的鏈接以向用戶提供控制播放的功能(好比一個UI界面)。
這時活動就會調用bindService()
來創建鏈接。而後調用服務中定義的方法來控制播放。
A later section, Remote procedure calls, has more details about binding to a service. 以後的章節會講到Remote procedure calls,那有更具體的綁定服務的信息。
An application can initiate a broadcast by passing an Intent object to methods like
, Context.sendBroadcast()
, and Context.sendOrderedBroadcast()
in any of their variations. Android delivers the intent to all interested broadcast receivers by calling their Context.sendStickyBroadcast()
methods. 程序可以經過向類似 onReceive()
Context.sendBroadcast()。
Context.sendOrderedBroadcast(),
Context.sendStickyBroadcast()。及它們的變種 的方法傳遞一個Intent對象來初始化一條廣播。
For more on intent messages, see the separate article, Intents and Intent Filters.
得到不少其它關於意圖的信息,查看單獨的章節Intents and Intent Filters。
A content provider is active only while it's responding to a request from a ContentResolver. And a broadcast receiver is active only while it's responding to a broadcast message. So there's no need to explicitly shut down these components.
內容提供者僅僅有在響應來自ContentResolver的請求時纔會處於激活狀態。廣播接收器僅僅有在響應廣播信息時才處於激活狀態。因此沒有必要顯式地關閉這些組件。
Activities, on the other hand, provide the user interface. They're in a long-running conversation with the user and may remain active, even when idle, as long as the conversation continues. Similarly, services may also remain running for a long time. So Android has methods to shut down activities and services in an orderly way:
活動,相反的。提供了用戶界面。他們會與用戶長時間地對話,而且可能在整個對話過程,即便處於空暇狀態,都保持執行狀態。
一樣的,服務也可能會執行很是長時間。所以。Android提供了下列的關閉活動和服務的方法:
finish()
method. One activity can shut down another activity (one it started with startActivityForResult()
) by calling finishActivity()
.活動可以經過調用他的finish()
方法進行關閉。
一個活動也可以調用finishActivity()
關閉還有一個活動(但僅僅能是由他調用startActivityForResult()
啓動的)。
stopSelf()
method, or by calling Context.stopService()
.一個服務可以經過調用他的stopSelf()
方法關閉。或者調用Context.stopService()
方法關閉。
Components might also be shut down by the system when they are no longer being used or when Android must reclaim memory for more active components. A later section, Component Lifecycles, discusses this possibility and its ramifications in more detail.
當組件不會再被使用時,或Android必須回收內存以執行其它組件時,系統會本身主動關閉組件。興許的Component Lifecycles章節中具體討論了這樣的可能和其後果。
Before Android can start an application component, it must learn that the component exists. Therefore, applications declare their components in a manifest file that's bundled into the Android package, the .apk
file that also holds the application's code, files, and resources.
Android啓動一個新的應用程序組件以前,他必須知道這個組件確實存在。
所以,應用程序在清單文件裏聲明瞭他的所有組件。
清單文件隨同應用程序的代碼、文件、資源一同打包在了Android包中,即.apk
文件裏。
The manifest is a structured XML file and is always named AndroidManifest.xml for all applications. It does a number of things in addition to declaring the application's components, such as naming any libraries the application needs to be linked against (besides the default Android library) and identifying any permissions the application expects to be granted.
清單文件是一個結構化的XML文件,同一時候在所有的應用程序都被命名爲AndroidManifest.xml。除了聲明應用程序的組件他還有很是多功用,好比爲所有應用程序需要進行鏈接的庫命名(除了默認的Android庫)還有識別所有應用程序指望得到的權限。
But the principal task of the manifest is to inform Android about the application's components. For example, an activity might be declared as follows:
但是清單文件的主要任務仍是爲Android提供應用程序的組件信息。好比,一個活動可能會像如下這樣定義:
<?xml version="1.0" encoding="utf-8"?> <manifest . . . > <application . . . > <activity android:name="com.example.project.FreneticActivity" android:icon="@drawable/small_pic.png" android:label="@string/freneticLabel" . . . > </activity> . . . </application> </manifest>
The name
attribute of the <activity>
element names the Activity
subclass that implements the activity. The icon
and label
attributes point to resource files containing an icon and label that can be displayed to users to represent the activity.
<activity>
元素的name
屬性命名了實現了activity的Activity
子類。icon
和label
屬性指向了 包括被顯示給用戶來表明這個活動的圖標和標題 的文件。
The other components are declared in a similar way — <service>
elements for services, <receiver>
elements for broadcast receivers, and <provider>
elements for content providers. Activities, services, and content providers that are not declared in the manifest are not visible to the system and are consequently never run. However, broadcast receivers can either be declared in the manifest, or they can be created dynamically in code (as BroadcastReceiver
objects) and registered with the system by calling
.Context.registerReceiver()
其它的組件的聲明方式類似——聲明服務用<service>元素,使用
<receiver>聲明廣播接收器。使用
<provider>
聲明內容提供者。
沒被聲明的活動,服務。內容提供者對Android系統是不可見的,所以永遠都不會被執行。但是廣播接收器可以在清單文件裏聲明也可在代碼中動態的建立(建立BroadcastReceiver
對象),而後調用
向系統註冊。Context.registerReceiver()
For more on how to structure a manifest file for your application, see The AndroidManifest.xml File.
不少其它有關怎樣爲您的應用程序構造一個清單文件,請參見The AndroidManifest.xml File。
An Intent object can explicitly name a target component. If it does, Android finds that component (based on the declarations in the manifest file) and activates it. But if a target is not explicitly named, Android must locate the best component to respond to the intent. It does so by comparing the Intent object to the intent filters of potential targets. A component's intent filters inform Android of the kinds of intents the component is able to handle. Like other essential information about the component, they're declared in the manifest file. Here's an extension of the previous example that adds two intent filters to the activity:
Intent對象會具體地指明一個目標組件。Android會找到那個組件(依據清單文件裏的聲明)而後激活它。
但是假設目標沒有被明白指出, Android就必須找到能響應這個意圖的最佳組件。Android將Intent對象和可能的目標組件的意圖匹配器進行比較來找出這個最佳組件。
組件的意圖匹配器告訴Android這個組件能操做什麼樣的意圖。就像組件的其它重要信息同樣,它們聲明於清單文件裏。
這裏是上邊那個樣例的增擴版。向活動中加入了兩個意圖匹配器。
<?xml version="1.0" encoding="utf-8"?
> <manifest . . . > <application . . . > <activity android:name="com.example.project.FreneticActivity" android:icon="@drawable/small_pic.png" android:label="@string/freneticLabel" . . . > <intent-filter . . . > <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <intent-filter . . . > <action android:name="com.example.project.BOUNCE" /> <data android:mimeType="image/jpeg" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> . . . </application> </manifest>
The first filter in the example — the combination of the action "android.intent.action.MAIN
" and the category "android.intent.category.LAUNCHER
" — is a common one. It marks the activity as one that should be represented in the application launcher, the screen listing applications users can launch on the device. In other words, the activity is the entry point for the application, the initial one users would see when they choose the application in the launcher.
樣例中的第一個意圖匹配器——"android.intent.action.MAIN
"動做和"android.intent.category.LAUNCHER
文件夾的結合——是常見的一種。它標明這個活動要在程序菜單上列出。就是要在列出設備上用戶可用的應用程序的那一屏。換句話說。這個活動是這個應用程序的入口點。用戶從菜單中選擇執行這個程序後見到的初始的活動。
The second filter declares an action that the activity can perform on a particular type of data.
第二個匹配器聲明瞭這個活動能處理某種形式的數據。
A component can have any number of intent filters, each one declaring a different set of capabilities. If it doesn't have any filters, it can be activated only by intents that explicitly name the component as the target.
一個組件可以有隨意多個意圖匹配器,每一個聲明這個組件的一種能力。假設一個組件沒有不論什麼意圖匹配器,他就僅僅能被明白的指明他做爲目標組件的意圖激活。
For a broadcast receiver that's created and registered in code, the intent filter is instantiated directly as an IntentFilter
object. All other filters are set up in the manifest.
對在代碼執行時建立並註冊的廣播接收器,意圖匹配器被做爲IntentFilter對象直接實例化。
For more on intent filters, see a separate document, Intents and Intent Filters.
有關意圖匹配器不少其它信息,參見單獨的Intents and Intent Filters文檔。
As noted earlier, one activity can start another, including one defined in a different application. Suppose, for example, that you'd like to let users display a street map of some location. There's already an activity that can do that, so all your activity needs to do is put together an Intent object with the required information and pass it to startActivity()
. The map viewer will display the map. When the user hits the BACK key, your activity will reappear on screen.
上邊提到過。一個活動能啓動還有一個活動,甚至是在別的應用程序中定義的活動。
設想,好比,您想讓用戶顯示某地的街區地圖。而且已經有了一個可以完畢此事的活動,因此您的活動要作的僅僅是將請求信息放進一個Intent對象中,將這個Intent對象傳遞給startActivity()
。地圖查看器這個活動就會顯示出地圖。當用戶點擊BACK按鈕以後,您的活動就會又一次出現在屏幕上。
To the user, it will seem as if the map viewer is part of the same application as your activity, even though it's defined in another application and runs in that application's process. Android maintains this user experience by keeping both activities in the same task. Simply put, a task is what the user experiences as an "application." It's a group of related activities, arranged in a stack. The root activity in the stack is the one that began the task — typically, it's an activity the user selected in the application launcher. The activity at the top of the stack is one that's currently running — the one that is the focus for user actions. When one activity starts another, the new activity is pushed on the stack; it becomes the running activity. The previous activity remains in the stack. When the user presses the BACK key, the current activity is popped from the stack, and the previous one resumes as the running activity.
對用戶來講這個地圖查看器就好像您的應用程序中的活動同樣,儘管這個地圖查看器是定義在其它應用程序中而且執行在那個應用程序的進程中。
Android將您的活動和那個借用的活動放在同一個task中。以維持用戶體驗。簡單來說任務就是用戶以爲好像是一個「應用程序」的東西。任務就是以棧的形式組織起來起來的相互關聯的一組活動。棧中最底部的是任務的起始活動——通常是用戶在滑出的程序列表中選擇啓動的活動。最頂部的是正在執行的活動——用戶正在關注操做的。當一個活動開啓還有一個時。新啓動的活動被壓入棧中;而且成爲正在執行的活動。舊一個活動還在棧中。當用戶按下BACK鍵後,正在執行的活動被彈出棧,舊一個恢復成爲正在執行的活動。
The stack contains objects, so if a task has more than one instance of the same Activity subclass open — multiple map viewers, for example — the stack has a separate entry for each instance. Activities in the stack are never rearranged, only pushed and popped.
棧中包括了對象。所以假設一個任務中開啓了 同一個Activity子類的 多個對象——好比,多個地圖瀏覽——則棧對每一個實例都有一個分開的入口。
棧中的活動不會被又一次排序。僅僅會被壓入、彈出。
A task is a stack of activities, not a class or an element in the manifest file. So there's no way to set values for a task independently of its activities. Values for the task as a whole are set in the root activity. For example, the next section will talk about the "affinity of a task"; that value is read from the affinity set for the task's root activity.
任務是由棧中的活動組成的,而不是清單文件裏聲明的某個類或元素。
因此沒法單獨爲一個任務設定肯定的活動的信息。任務的所有信息都是設定在根活動中的。好比,下一個章節會講到「任務的親和度」。親和度信息就是從任務的根活動中獲取的。
All the activities in a task move together as a unit. The entire task (the entire activity stack) can be brought to the foreground or sent to the background. Suppose, for instance, that the current task has four activities in its stack — three under the current activity. The user presses the HOME key, goes to the application launcher, and selects a new application (actually, a new task). The current task goes into the background and the root activity for the new task is displayed. Then, after a short period, the user goes back to the home screen and again selects the previous application (the previous task). That task, with all four activities in the stack, comes forward. When the user presses the BACK key, the screen does not display the activity the user just left (the root activity of the previous task). Rather, the activity on the top of the stack is removed and the previous activity in the same task is displayed.
任務中的所有活動是做爲一個整體運轉的。整個任務(一個棧的所有活動)可以被送到前臺或推到後臺。假設,好比,現在有一個正在執行的任務,棧中有四個活動 ——正在執行的活動下邊有三個。這是用戶按下了HOME鍵,回到了應用程序的列表而後執行了一個新的應用程序(其實,是一個新的任務)。則舊一個任務就被推到了後臺。新一個任務的根活動被現實。一段時間事後用戶回到了應用程序列表,又選擇了舊一個應用程序(舊一個任務)。則舊一個任務的所有棧中的四個活動就都被送到了前臺。這時用戶假設按下BACK建屏幕不會回到用戶剛離開的活動(就是新一個任務的跟活動)。而是舊一個任務的棧頂活動被彈出。下一個活動頂上,並被顯示出來。
The behavior just described is the default behavior for activities and tasks. But there are ways to modify almost all aspects of it. The association of activities with tasks, and the behavior of an activity within a task, is controlled by the interaction between flags set in the Intent object that started the activity and attributes set in the activity's <activity>
element in the manifest. Both requester and respondent have a say in what happens.
上面描寫敘述的過程是活動和任務的默認動做流程。
但是那個流程很是多方面都是可改動的。活動和任務的組合還有任務中的活動是由 開啓活動的Intent對象中設定的控制標 和 清單文件裏活動的<activity>
元素的屬性 共同控制的。
In this regard, the principal Intent flags are:
這樣的狀況下。重要的Intent控制標有:
FLAG_ACTIVITY_NEW_TASK
FLAG_ACTIVITY_CLEAR_TOP
FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
FLAG_ACTIVITY_SINGLE_TOP
The principal <activity>
attributes are:
重要的<activity>
屬性有:
taskAffinity
launchMode
allowTaskReparenting
clearTaskOnLaunch
alwaysRetainTaskState
finishOnTaskLaunch
The following sections describe what some of these flags and attributes do, how they interact, and what considerations should govern their use.
如下的章節描寫敘述了這些控制標和屬性的做用,怎樣相連發生做用。在使用過程當中的注意事項。
By default, all the activities in an application have an affinity for each other — that is, there's a preference for them all to belong to the same task. However, an individual affinity can be set for each activity with the taskAffinity
attribute of the <activity>
element. Activities defined in different applications can share an affinity, or activities defined in the same application can be assigned different affinities. The affinity comes into play in two circumstances: When the Intent object that launches an activity contains the FLAG_ACTIVITY_NEW_TASK
flag, and when an activity has its allowTaskReparenting
attribute set to "true
".
默認的,一個應用程序中的所有活動之間都互有 親和度——就是他們屬於一個任務的優先權。
但是,您可以經過每一個活動的<activity>
元素的taskAffinity
屬相爲某個活動設定單獨的親和度。不一樣程序中定義的活動可以共享一個親和度,一個應用程序中的不一樣活動可以定義不一樣的親和度。親和度在兩種狀況下實用:一種狀況是當激活活動的Intent對象包括了FLAG_ACTIVITY_NEW_TASK
控制標,還有一種狀況是活動將allowTaskReparenting
屬性設置爲了"true
"。
FLAG_ACTIVITY_NEW_TASK
flag——
FLAG_ACTIVITY_NEW_TASK
控制標
startActivity()
. It's pushed onto the same stack as the caller. However, if the Intent object passed to
startActivity()
contains the
FLAG_ACTIVITY_NEW_TASK
flag, the system looks for a different task to house the new activity. Often, as the name of the flag implies, it's a new task. However, it doesn't have to be. If there's already an existing task with the same affinity as the new activity, the activity is launched into that task. If not, it begins a new task.
startActivity()
向任務中加入一個活動。新加入的活動會壓入加入他的活動所在棧。但是。假設傳遞給
startActivity()
的Intent對象中含有
FLAG_ACTIVITY_NEW_TASK
控制標。系統會將新活動壓入別的棧。一般,就像控制標的字面意思同樣。會是一個新的任務。但是,不是必定要壓入新的棧。假設已經有了一個親和度和新活動一樣的任務,活動就被壓入那個任務的棧中。假設沒有,纔會新建任務。
allowTaskReparenting
attribute——
allowTaskReparenting
屬性
allowTaskReparenting
attribute set to "
true
", it can move from the task it starts in to the task it has an affinity for when that task comes to the fore. For example, suppose that an activity that reports weather conditions in selected cities is defined as part of a travel application. It has the same affinity as other activities in the same application (the default affinity) and it allows reparenting. One of your activities starts the weather reporter, so it initially belongs to the same task as your activity. However, when the travel application next comes forward, the weather reporter will be reassigned to and displayed with that task.
allowTaskReparenting
屬性設爲"
true
",他可以 在具備親和度的任務被送到前臺時 從開啓他的任務移到親和的任務中。好比。假設有一個已經作好的旅行的應用程序。定義了一個報告選擇的城市的天氣狀況的活動。這個活動和這個應用程序中其它活動有一樣親和度(默認的親和度),同一時候贊成重定父級。您本身的一個應用程序中的一個活動開啓了這個天氣報告活動。他初始狀況是處於您本身的應用程序的任務中。但是當這個旅行應用程序執行並被切換到前臺後,天氣報告活動就會被又一次鏈接 到旅行應用程序中,並在那個任務中顯示。
If an .apk
file contains more than one "application" from the user's point of view, you will probably want to assign different affinities to the activities associated with each of them.
假設一個.apk
文件包括了多個用戶看來的「應用程序」。您可能會爲和每一個「應用程序」相關的活動設定不一樣的親和度。
There are four different launch modes that can be assigned to an <activity>
element's launchMode
attribute:
如下是可以被設爲<activity>
元素launchMode
屬性的四種啓動模式:
"standard
" (the default mode) ——標準(默認的)
"singleTop
"
"singleTask
"
"singleInstance
"
The modes differ from each other on these four points:
每一個任務都有如下四方面的特色:
standard
" and "singleTop
" modes, it's the task that originated the intent (and called startActivity()
) — unless the Intent object contains theFLAG_ACTIVITY_NEW_TASK
flag. In that case, a different task is chosen as described in the previous section, Affinities and new tasks. standard
"和"singleTop
"模式。是裝入發出意圖(調用了startActivity()
)的任務——除非Intent對象含有FLAG_ACTIVITY_NEW_TASK
控制標。後種狀況流程如前邊Affinities and new tasks章節所述。In contrast, the "singleTask
" and "singleInstance
" modes mark activities that are always at the root of a task. They define a task; they're never launched into another task.
相反的,使用"singleTask
"標記和"singleInstance
"標記始終爲根活動的活動。
開啓這樣的活動會新建一個任務。而不是裝入某個正在執行的任務。
Whether there can be multiple instances of the activity. A "standard
" or "singleTop
" activity can be instantiated many times. They can belong to multiple tasks, and a given task can have multiple instances of the same activity.
standard"
或"singleTop
"活動可以被屢次實例化。他們可以屬於多個任務,一樣的活動可以在一個肯定的任務中有多個實例。
In contrast, "singleTask
" and "singleInstance
" activities are limited to just one instance. Since these activities are at the root of a task, this limitation means that there is never more than a single instance of the task on the device at one time.
singleTask
和"singleInstance
"的活動僅僅能有一個實例。因爲這些活動是任務的根活動,這樣的限制意味着一個任務在同一時間僅僅能有一個。Whether the instance can have other activities in its task. A "singleInstance
" activity stands alone as the only activity in its task. If it starts another activity, that activity will be launched into a different task regardless of its launch mode — as if FLAG_ACTIVITY_NEW_TASK
was in the intent. In all other respects, the "singleInstance
" mode is identical to "singleTask
".
所在任務中是否贊成有其它活動。"singleInstance
"活動單獨執行在一個任務中。假設他開啓還有一個活動。新一個活動不論啓動模式都會執行在新任務中——就好像用帶有FLAG_ACTIVITY_NEW_TASK
控制標的Intent對象激活似的。其它方面"singleInstance
"與"singleTask
"一樣。
The other three modes permit multiple activities to belong to the task. A "singleTask
" activity will always be the root activity of the task, but it can start other activities that will be assigned to its task. Instances of "standard
" and "singleTop
" activities can appear anywhere in a stack.
另外三個模式贊成任務中存在多個活動。
"singleTask
"活動將老是任務的根活動,但是由他啓動的其它活動會被裝入他所在的任務。"standard
"和"singleTop
"活動能在任務棧中不論什麼不論什麼位置出現。
standard
" mode, a new instance is created to respond to every new intent. Each instance handles just one intent. For the "singleTop
" mode, an existing instance of the class is re-used to handle a new intent if it resides at the top of the activity stack of the target task. If it does not reside at the top, it is not re-used. Instead, a new instance is created for the new intent and pushed on the stack. standard
"的模式,每次得到新意圖時都會用新的實例響應。每一個實例響應一個意圖。"singleTop
"模式中。假設意圖響應類實例存在且在 意圖的目標任務 棧的棧頂,那麼意圖響應類實例將會被重用。假設存在但再也不棧頂,則不會被重用。
新實例被建立並壓入棧頂。
For example, suppose a task's activity stack consists of root activity A with activities B, C, and D on top in that order, so the stack is A-B-C-D. An intent arrives for an activity of type D. If D has the default "standard
" launch mode, a new instance of the class is launched and the stack becomes A-B-C-D-D. However, if D's launch mode is "singleTop
", the existing instance is expected to handle the new intent (since it's at the top of the stack) and the stack remains A-B-C-D.
好比,假設 一個任務的幾個活動是 根活動A,活動B。C。D 的順序。棧內就是A-B-C-D。
這時收到一個類D進行響應的意圖。假設D是"standard
"啓動模式,則將建立類的新實例,棧內變成A-B-C-D-D。但是假設D是"singleTop
"啓動模式,用以響應新意圖的實例已經存在(而且已經在棧頂),棧保持A-B-C-D不變。
If, on the other hand, the arriving intent is for an activity of type B, a new instance of B would be launched no matter whether B's mode is "standard
" or "singleTop
" (since B is not at the top of the stack), so the resulting stack would be A-B-C-D-B.
假設,還有一種狀況。收到一個類B響應的意圖。無論B的啓動類型是"standard
"仍是"singleTop
"(因爲B不在棧頂),新實例都會被建立,以後的棧會變成A-B-C-D-B。
As noted above, there's never more than one instance of a "singleTask
" or "singleInstance
" activity, so that instance is expected to handle all new intents. A "singleInstance
" activity is always at the top of the stack (since it is the only activity in the task), so it is always in position to handle the intent. However, a "singleTask
" activity may or may not have other activities above it in the stack. If it does, it is not in position to handle the intent, and the intent is dropped. (Even though the intent is dropped, its arrival would have caused the task to come to the foreground, where it would remain.)
就像前面已經提到過的,"singleTask
"和"singleInstance
"活動的類永遠不可能會出現多個實例。
因此他們的類就會處理所有的收到的意圖。"singleInstance
"活動永遠是任務的棧的最頂活動(因爲他是任務中的惟一活動),所以他也總可以處理一個意圖。但是在"singleTask
"活動棧位之上可能也可能沒有另外的活動。假設有,那麼他就不能對新到的意圖進行處理,這個意圖就丟失了。(即便意圖已經丟失,意圖的收到也會出發任務使其被送到並保持在前臺。)
When an existing activity is asked to handle a new intent, the Intent object is passed to the activity in an
call. (The intent object that originally started the activity can be retrieved by calling onNewIntent()
.)getIntent()
當一個已有的活動被請求去處理一個新的意圖。Intent對象會經過onNewIntent()
的調用傳遞給這個活動。(傳遞進來的原始的Intent對象可以經過調用getIntent()
獲取。)
Note that when a new instance of an Activity is created to handle a new intent, the user can always press the BACK key to return to the previous state (to the previous activity). But when an existing instance of an Activity handles a new intent, the user cannot press the BACK key to return to what that instance was doing before the new intent arrived.
注意,當建立一個新的Activity類的實例來處理一個新收到的意圖時。用戶可以按BACK鍵回到上一個狀態(上一個活動)。但是使用一個已有的Activity類實例操做新收到的意圖時。用戶不能經過按下BACK鍵回到這個實例在接受到新意圖以前的狀態。
For more on launch modes, see the description of the <activity>
element.
啓動模式的不少其它信息,參見清單文件<activity>
元素的描寫敘述。
If the user leaves a task for a long time, the system clears the task of all activities except the root activity. When the user returns to the task again, it's as the user left it, except that only the initial activity is present. The idea is that, after a time, users will likely have abandoned what they were doing before and are returning to the task to begin something new.
假設用戶長時間沒有使用一個執行着的任務,系統會將任務和其中除根活動之外的所有活動清理掉。當用戶再次使用這個任務時,也是用戶當初離開的緣由。但願僅僅顯示第一個活動,即初始狀態。
咱們以爲,用戶很是長時間不用這個任務,就是放棄了先前作出的改動,再次回到這個任務是要又一次開始。
That's the default. There are some activity attributes that can be used to control this behavior and modify it:
這是默認的狀況,但是您可以更改下列的活動的屬性來控制這個機制:
alwaysRetainTaskState
attribute——
alwaysRetainTaskState
屬性
true
" in the root activity of a task, the default behavior just described does not happen. The task retains all activities in its stack even after a long period.
true
"。上面描寫敘述的默認的流程就不會發生。任務會保持其棧中所有的活動,無論用戶有多長時間沒有使用。
clearTaskOnLaunch
attribute——
clearTaskOnLaunch
屬性
true
" in the root activity of a task, the stack is cleared down to the root activity whenever the user leaves the task and returns to it. In other words, it's the polar opposite of
alwaysRetainTaskState
. The user always returns to the task in its initial state, even after a momentary absence.
true
"。用戶離開任務後一回來。系統就清除棧中除根活動外的所有活動。
換句話說,這是alwaysRetainTaskState
的極端反面狀況。即便用戶僅僅是離開一會,任務也會變回初始的狀態。
finishOnTaskLaunch
attribute——
finishOnTaskLaunch
屬性
clearTaskOnLaunch
, but it operates on a single activity, not an entire task. And it can cause any activity to go away, including the root activity. When it's set to "
true
", the activity remains part of the task only for the current session. If the user leaves and then returns to the task, it no longer is present.
clearTaskOnLaunch
。但是
finishOnTaskLaunch
針對對單一活動。不是整個任務。
而且他能關閉棧中不論什麼活動。包括根活動。當他被設爲"true
"時,這個活動僅僅是當前屬於這個任務,用戶離開。再回到這個任務,他就被關閉了。
There's another way to force activities to be removed from the stack. If an Intent object includes the
flag, and the target task already has an instance of the type of activity that should handle the intent in its stack, all activities above that instance are cleared away so that it stands at the top of the stack and can respond to the intent. If the launch mode of the designated activity is "FLAG_ACTIVITY_CLEAR_TOP
standard
", it too will be removed from the stack, and a new instance will be launched to handle the incoming intent. That's because a new instance is always created for a new intent when the launch mode is "standard
".
還有一種方法能將活動從棧中強行移除。
假設一個Intent對象包括有FLAG_ACTIVITY_CLEAR_TOP
控制標,而且目標任務中已經有一個處理此意圖的活動的實例,則所有此活動棧位之上的所有活動實例都被移除,而後此活動可以對意圖進行響應。假設此活動的啓動模式是"standard
"。那麼他本身也會被移除,新活動被創建,啓動。來響應這個意圖。因爲假設啓動模式是"standard
",則每一個意圖都會用一個新的實例進行處理。
FLAG_ACTIVITY_CLEAR_TOP
is most often used in conjunction with FLAG_ACTIVITY_NEW_TASK
. When used together, these flags are a way of locating an existing activity in another task and putting it in a position where it can respond to the intent.
FLAG_ACTIVITY_CLEAR_TOP
通常會和FLAG_ACTIVITY_NEW_TASK
聯合使用。一塊兒使用時,這個組合是 找到還有一個任務中的已有活動而後將它轉入新的任務中以響應一個意圖的 一種方法。
An activity is set up as the entry point for a task by giving it an intent filter with "android.intent.action.MAIN
" as the specified action and "android.intent.category.LAUNCHER
" as the specified category. (There's an example of this type of filter in the earlier Intent Filters section.) A filter of this kind causes an icon and label for the activity to be displayed in the application launcher, giving users a way both to launch the task and to return to it at any time after it has been launched.
您可以 經過給活動加入一個"android.intent.action.MAIN
" 的意圖匹配器來指定動做,一個"android.intent.category.LAUNCHER
"來指定其顯示在應用程序列表中 來將這個活動設置爲任務的入口活動。(上邊的Intent Filters章節中有這兩個類型的意圖匹配器的樣例。
)這樣的匹配器會使應用程序在應用程序列表中顯示其圖標和標題,使用戶能執行他或在執行後的不論何時回到他。
This second ability is important: Users must be able to leave a task and then come back to it later. For this reason, the two launch modes that mark activities as always initiating a task, "singleTask
" and "singleInstance
", should be used only when the activity has a MAIN
and LAUNCHER
filter. Imagine, for example, what could happen if the filter is missing: An intent launches a "singleTask
" activity, initiating a new task, and the user spends some time working in that task. The user then presses the HOME key. The task is now ordered behind and obscured by the home screen. And, because it is not represented in the application launcher, the user has no way to return to it.
第二個功能很是重要:用戶必須可以在離開這個任務後能再回到當初的狀態。
因爲這個緣由,將活動設定爲切回後初始化任務的"singleTask
"和"singleInstance
"啓動模式僅僅能用在有MAIN
和LAUNCHER
匹配器的活動裏。
設想。好比。假設用在沒有這兩個匹配器的活動中會出現什麼現象:一個意圖激活了一個"singleTask
"活動。初始化了一個新的任務,用戶在這個任務中作了點什麼,而後用戶按下HOME鍵。這個活動就被退到後臺,並被桌面屏幕掩蓋,而後。因爲他不在應用程序列表中顯示,用戶無法再回到那個活動中去了。
A similar difficulty attends the FLAG_ACTIVITY_NEW_TASK
flag. If this flag causes an activity to begin a new task and the user presses the HOME key to leave it, there must be some way for the user to navigate back to it again. Some entities (such as the notification manager) always start activities in an external task, never as part of their own, so they always put FLAG_ACTIVITY_NEW_TASK
in the intents they pass to startActivity()
. If you have an activity that can be invoked by an external entity that might use this flag, take care that the user has a independent way to get back to the task that's started.
類似的難題在使用FLAG_ACTIVITY_NEW_TASK
控制標時也會出現。
假設這個控制標使活動開啓了一個新的任務而後用戶按下HOME鍵離開這個活動,他也沒有辦法再回來了。
有些東西(好比通知管理器)老是在一個新的任務中打開活動。歷來不在本身的任務中打開,因此他們總將包括FLAG_ACTIVITY_NEW_TASK
的意圖傳遞給startActivity()
。因此假設您有一個會被其它東西以這個控制標調用的活動。請注意用戶有獨立的回到這個活動的方法。
For those cases where you don't want the user to be able to return to an activity, set the <activity>
element's finishOnTaskLaunch
to "true
". See Clearing the stack, earlier.
假設您但願用戶離開活動後就不能再回到這個活動,可以將<activity>
元素的finishOnTaskLaunch
設爲"true
"。查看上邊提到過的Clearing the stack。
When the first of an application's components needs to be run, Android starts a Linux process for it with a single thread of execution. By default, all components of the application run in that process and thread.
當應用程序的第一個組件需要執行是。Android爲其分配一個Linux進程,這個進程僅僅有一個執行線程。默認的,這個應用程序的所有組件執行在那個進程的線程中。
However, you can arrange for components to run in other processes, and you can spawn additional threads for any process.
但是,您可以將一些組件安排在別的進程中,而且您可以爲不論什麼進程加入線程。
The process where a component runs is controlled by the manifest file. The component elements — <activity>
, <service>
, <receiver>
, and <provider>
— each have a process
attribute that can specify a process where that component should run. These attributes can be set so that each component runs in its own process, or so that some components share a process while others do not. They can also be set so that components of different applications run in the same process — provided that the applications share the same Linux user ID and are signed by the same authorities. The <application>
element also has a process
attribute, for setting a default value that applies to all components.
組件執行在那個進程中是由清單文件進行設定的。
組件元素——<activity>
, <service>
。<receiver>
和<provider>
——都有一個process
屬性來指定組件應該執行在哪一個進程中。您可以設定這個屬性,使每一個組件執行在本身的進程中。或者讓某些組件共享一個進程而其它的不。您甚至可以設定不一樣的應用程序的組件執行在同一個進程中——這兩個不一樣的應用程序須是由同一做者簽名。且分享同一個Linux 用戶ID。<application>
元素也有一個process
屬性。來設定對所有組件的默認設定。
All components are instantiated in the main thread of the specified process, and system calls to the component are dispatched from that thread. Separate threads are not created for each instance. Consequently, methods that respond to those calls — methods like
that report user actions and the lifecycle notifications discussed later in the Component Lifecycles section — always run in the main thread of the process. This means that no component should perform long or blocking operations (such as networking operations or computation loops) when called by the system, since this will block any other components also in the process. You can spawn separate threads for long operations, as discussed under Threads, next.View.onKeyDown()
所有的組件都是在指定進程的主線程中實例化的,對組件的系統調用也是由主線線程發出的。
系統不會爲每一個實例創建新的線程。
因此,對系統調用進行響應的方法,那些像 報告用戶操做的 View.onKeyDown()
和在後邊Component Lifecycles章節提到的指示生命週期 的方法老是執行在進程的主線程中。
這就是說當系統對組件進行調用時。組件不該進行長時間的或等待性的操做(好比網絡操做或循環運算),因爲這樣會使同在這個進程中的其它組件執行受阻。您可以像下邊Threads中講的那樣,爲耗時的操做創建單獨的進程。
Android may 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 are consequently destroyed. A process is restarted for those components when there's again work for them to do.
Android系統可能會在某些時候結束一個進程,當內存不足且被其它對用戶來講更緊要的進程請求時。
所以,在此進程中的Android組件會被銷燬。當這些組件有新的事要作時,系統會爲他們從新啓動進程。
When deciding which processes to terminate, Android weighs their relative importance to the user. For example, it more readily shuts down a process with activities that are no longer visible on screen than a process with visible activities. The decision whether to terminate a process, therefore, depends on the state of the components running in that process. Those states are the subject of a later section, Component Lifecycles.
Android權衡對用戶的重要性關係來決定結束哪一個進程。
好比,一個不是正在顯示的進程比正在顯示的進程更easy被結束。是否要結束某個進程是由裏邊執行的組件的狀態決定的。組建的狀態是下邊Component Lifecycles章節的主題。
Even though you may confine your application to a single process, there will likely be times when you will need to spawn a thread to do some background work. Since the user interface must always be quick to respond to user actions, the thread that hosts an activity should not also host time-consuming operations like network downloads. Anything that may not be completed quickly should be assigned to a different thread.
即便您將您的應用程序限制在了一個進程中,那您也很是可能有需要新建一個線程來進行後臺工做的可能。因爲用戶界面必須老是能高速地響應用戶的動做。承載着活動的線程不能同一時候還承載者像網絡下載這樣的耗時的操做。所有不能立馬完畢的操做都應爲其單獨創建線程。
Threads are created in code using standard Java Thread
objects. Android provides a number of convenience classes for managing threads — Looper
for running a message loop within a thread, Handler
for processing messages, andHandlerThread
for setting up a thread with a message loop.
線程在代碼中使用標準的Java Thread
對象創建。Android提供了很是多方便的管理線程的類——使用一個線程執行消息循環可以使用Looper
,Handler
響應消息。HandlerThread
建立帶有消息循環的線程。
Android has a lightweight mechanism for remote procedure calls (RPCs) — where a method is called locally, but executed remotely (in another process), with any result returned back to the caller. This entails decomposing the method call and all its attendant 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, and reassembling and reenacting the call there. Return values have to be transmitted in the opposite direction. Android provides all the code to do that work, so that you can concentrate on defining and implementing the RPC interface itself.
Android 有一個輕量級的遠程過程調用的機制(RPCs)——使得方法在本地調用,而後遠程執行(在還有一個進程中)。並將所有結果返回本地。這需要將方法的調用和隨之的數據解釋成操做系統可以識別的級別,將其從本地進程和地址空間傳送到遠程端的進程和地址空間中。在遠程端又一次裝配和組織。返回數據傳遞過程相反。
Android提供了所有完畢這些過程的代碼。因此您可以將精力集中在RPC接口的定義和實現上。
An RPC interface can include only methods. All methods are executed synchronously (the local method blocks until the remote method finishes), even if there is no return value.
RPC接口可以僅僅包括方法。所有的方法都是同步執行的(本地方法會等待遠程方法),在沒有返回值的狀況下也是這樣。
In brief, the mechanism works as follows: You'd begin by declaring the RPC interface you want to implement using a simple IDL (interface definition language). From that declaration, the aidl
tool generates a Java interface definition that must be made available to both the local and the remote process. It contains two inner class, as shown in the following diagram:
簡單來說。RPC機制是這樣的流程:首先,您使用簡單的IDL(接口定義語言)對您想要實現的RPC接口進行聲明。在生聲明中,您需要使用aidl
工具生成一個本地和遠程端進程都可以使用的Java接口定義。定義中含有兩個內部類,如下圖標顯示了這個結構:
The inner classes have all the code needed to administer remote procedure calls for the interface you declared with the IDL. Both inner classes implement the IBinder
interface. One of them is used locally and internally by the system; the code you write can ignore it. The other, called Stub, extends the Binder
class. In addition to internal code for effectuating the IPC calls, it contains declarations for the methods in the RPC interface you declared. You would subclass Stub to implement those methods, as indicated in the diagram.
內部類中含有所有 用以管理您使用IDL聲明的接口的遠程過程調用 的代碼。兩個內部類都實現了IBinder接口。一個被系統本地地。內部地使用;您本身寫的代碼會忽略掉它們。
還有一個,叫作Stub,由Binder
類派生。不只含有執行IPC調用的代碼,還含有您聲明的RPC接口中方法的聲明。就像圖標中顯示的。您應該繼承Stub類來實現這些方法。
Typically, the remote process would be managed by a service (because a service can inform the system about the process and its connections to other processes). It would have both the interface file generated by the aidl
tool and the Stub subclass implementing the RPC methods. Clients of the service would have only the interface file generated by the aidl
tool.
典型的狀況是,遠程端的進程是由一個服務進行管理的(因爲服務能向系統告知 這個進程 還有 這個進程和其它進程間鏈接的 信息)。您應在aidl
工具產生的接口文件和Stub子類中均實現RPC方法。server的client應該僅僅有aidl
工具生成的接口文件。
Here's how a connection between a service and its clients is set up:
這是server和其client創建鏈接的流程:
onServiceConnected()
and onServiceDisconnected()
methods so they can be notified when a successful connection to the remote service is established, and when it goes away. They would then call bindService()
to set up the connection. server的client(即本地端)會實現
onServiceConnected()和
onServiceDisconnected()方法。而後client在在遠程服務鏈接創建或丟失時得知這一信息。而後client會調用bindService()
來對鏈接進行設定。onBind()
method would be implemented to either accept or reject the connection, depending on the intent it receives (the intent passed to bindService()
). If the connection is accepted, it returns an instance of the Stub subclass. 依據接收的意圖(意圖被傳遞到bindService()
)服務的
onBind()方法會被實現於接受或拒絕鏈接。假設鏈接被接受,方法返回一個Stub子類的實例。onServiceConnected()
method and passes it an IBinder object, a proxy for the Stub subclass managed by the service. Through the proxy, the client can make calls on the remote service. 假設服務接受了鏈接,Android調用client的onServiceConnected()
方法而且傳遞給它一個IBinder對象。IBinder對象是由服務管理的Stub類的一個代理。經過這個代理,client可以調用遠程端上的服務。This brief description omits some details of the RPC mechanism. For more information, see Designing a Remote Interface Using AIDL and the IBinder
class description.這個簡要的RPC機制介紹省略了一些細節。不少其它信息請看Interface Using AIDL和IBinder
類的介紹。
In a few contexts, the methods you implement may 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 — as in the RPC mechanism discussed in the previous section. When a call on a method implemented in an IBinder object originates in the same process as the IBinder, 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 Android maintains in the same process as the IBinder; it's not executed in the main thread of the process. For example, whereas a service's onBind()
method would be called from the main thread of the service's process, methods implemented in the object that onBind()
returns (for example, a Stub subclass that implements RPC methods) would be called from threads in the pool. Since services 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.
這樣的狀況主要出現在能被遠程調用的方法中——像在上邊討論的RPC機制。當一個對 IBinder對象中實現的一個方法 進行的調用來自IBinder自己所在線程時,方法就執行在調用者所在線程中。但是。當調用來自另一個進程時,方法會執行在從 Android爲IBinder進程保持的線程池 中選擇的一個線程中,而不是執行在另外那個進程的主線程中。
好比,服務的onBind()
方法的的調用來自服務的進程的主線程,onBind()
返回的對象的實現的方法(好比,Stub類實現的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()
, and update()
— are called from a pool of threads in the content provider's process, not the main thread of the process. Since these methods may be called from any number of threads at the same time, they too must be implemented to be thread-safe.getType()
類似的,內容提供者可以接受來自其它進程的數據請求。儘管ContentResolver和ContentProvider類隱藏了實現管理進程間通訊的方法的細節,但是響應這些請求的ContentProvider方法——
。query()
。insert()
。delete()
和update()
方法——是從內容提供者進程的線程池中調用的。而不是主線程。所以,這些方法可能會在同一時間被多個線程調用。他們的實現對多進程調用也必須是安全的。getType()
Application components have a lifecycle — a beginning when Android instantiates them to respond to intents through to an end when the instances are destroyed. In between, they may sometimes be active or inactive,or, in the case of activities, visible to the user or invisible. This section discusses the lifecycles of activities, services, and broadcast receivers — including the states that they can be in during their lifetimes, the methods that notify you of transitions between states, and the effect of those states on the possibility that the process hosting them might be terminated and the instances destroyed.
應用程序的組建有生命週期——從Android爲其實例化以響應意圖開始 到 實例被銷燬結束。
中間這段時間,這些組件可能正在活動,也可能不在。或者對活動來說是可見或不可見。
這一節討論了 活動、服務、廣播接收器的生命週期——包括他們在生命週期內可能的狀態 ,狀態轉換時的通知方式 ,和這些狀態對承載組建的進程被結束(同一時候進程中的實例被銷燬)的可能性的影響。
An activity has essentially three states:
活動本質上有三個狀態:
It is paused if it has lost focus but is still visible to the user. That is, another activity lies on top of it and that activity either is transparent or doesn't cover the full screen, so some of the paused activity can show through. A paused activity is completely alive (it maintains all state and member information and remains attached to the window manager), but can be killed by the system in extreme low memory situations. 失去用戶關注,但是仍然是可見的 是paused(暫停)狀態。就是說,還有一個透明或不覆蓋整個屏幕的活動覆蓋在了這個活動之上。所以部分paused的活動的界面仍是顯示出來的。
暫停的活動依然是存活的(他保持着所有的狀態和成員信息而且保持着和窗體管理器的聯繫),但是會在系統執行內存極低的狀況下被關閉。
It is stopped if it is completely obscured by another activity. It still retains all state and member information. However, it is no longer visible to the user so its window is hidden and it will often be killed by the system when memory is needed elsewhere. 當一個活動被還有一個活動全然覆蓋時。就是stopped(中止)狀態。
中止的活動保留着所有的狀態和成員信息。但是,因爲他已經處於不可見狀態,他的窗體就被隱藏了,而且一般系統會在內存需要用在別的地方時關閉中止的活動。
If an activity is paused or stopped, the system can drop it from memory either by asking it to finish (calling its finish()
method), or simply killing its process. When it is displayed again to the user, it must be completely restarted and restored to its previous state.
假設一個活動處於暫停或中止狀態,系統會經過 勒令其完畢工做並推出(調用其finish()方法)或簡單的結束其所在進程 來將其從內存中清理掉。
當他再次顯示給用戶是=時,他必須請全然的又一次啓動並恢復到以前的狀態。
As an activity transitions from state to state, it is notified of the change by calls to the following protected methods:
活動在上述幾種狀態間變更時。系統會調用下列的protected(受保護)的方法對其進行通知:
void onCreate(Bundle savedInstanceState)
void onStart()
void onRestart()
void onResume()
void onPause()
void onStop()
void onDestroy()
All of these methods are hooks that you can override to do appropriate work when the state changes. All activities must implement
to do the initial setup when the object is first instantiated. Many will also implement onCreate()
to commit data changes and otherwise prepare to stop interacting with the user.onPause()
所有這些方法都是掛鉤,你可以重寫狀態變化時的動做。所有活動都必須實現onCreate(),從而在對象第一次實例化後進行初始化設置。
不少活動還要實現
onPause()來確認數據變化或者準備中止與用戶的交互。
An implementation of any activity lifecycle method should always first call the superclass version. For example:
所有的活動的生命週期方法的實現都應首先調用父類的實現。
好比:
protected void onPause() { super.onPause(); . . . }
Taken together, these seven methods define the entire lifecycle of an activity. There are three nested loops that you can monitor by implementing them:
總的來講,這七種方法肯定活動的整個生命週期。實現生命週期後,您可以對生命週期的這幾個嵌套循環進行監控:
onCreate()
through to a single final call to onDestroy()
. An activity does all its initial setup of "global" state in onCreate()
, and releases all remaining resources inonDestroy()
. For example, if it has a thread running in the background to download data from the network, it may create that thread in onCreate()
and then stop the thread inonDestroy()
. 從調用
onCreate()一直到結束性的
onDestroy()的調用。活動在onCreate()
中進行所有「全局」狀態的初始化,後釋放所有佔用的資源好比,假設一個活動有一個後臺的從網絡上下載數據的線程,活動可能會使用onCreate()
建立線程,使用onDestroy()
中止線程。The visible lifetime of an activity happens between a call to
until a corresponding call to onStart()
. During this time, the user can see the activity on-screen, though it may not be in the foreground and interacting with the user. Between these two methods, you can maintain resources that are needed to show the activity to the user. For example, you can register a onStop()
BroadcastReceiver
in onStart()
to monitor for changes that impact your UI, and unregister it in onStop()
when the user can no longer see what you are displaying. The onStart()
and onStop()
methods can be called multiple times, as the activity alternates between being visible and hidden to the user. 活動可見的時間是
onStart()的調用到相應的
onStop()的調用之間的時間。這段時間用戶可以在屏幕上看到這個活動,即使這個活動可能不在前臺,沒在和用戶進行交互。
在這兩個方法的調用之間的時間,您可以保持將活動展示給用戶的資源。好比,您可以在onStart()
中註冊一個BroadcastReceiver來監控UI的變化。而後在用戶不能再看到您要顯示的後在
onStop()
中註銷它。活動在可見和隱藏間切換過程當中,onStart()
和onStop()
會被調用屢次。
The foreground lifetime of an activity happens between a call to
until a corresponding call to onResume()
. During this time, the activity is in front of all other activities on screen and is interacting with the user. An activity can frequently transition between the resumed and paused states — for example, onPause()
onPause()
is called when the device goes to sleep or when a new activity is started, onResume()
is called when an activity result or a new intent is delivered. Therefore, the code in these two methods should be fairly lightweight. 活動的前臺時間是
和相應的onResume()
onPause()的調用之間的時間。這段時間中。活動處在其它活動之上。並和用戶進行交互。
活動可以在暫停和繼續之間屢次切換——好比,當設備休眠或啓動了新的活動。onPause()
會被調用,收到新啓動活動返回結果或舊活動收到新意圖時,onResume()
會被調用。因此這兩個方法中的代碼應絕對輕量。
The following diagram illustrates these loops and the paths an activity may take between states. The colored ovals are major states the activity can be in. The square rectangles represent the callback methods you can implement to perform operations when the activity transitions between states.
如下的圖標演示了這三個循環還有活動在狀態間轉換的步驟。
彩色的橢圓是活動可能處於的狀態。直角矩形是您可以實現的 在狀態改變時執行操做的 回調方法。
The following table describes each of these methods in more detail and locates it within the activity's overall lifecycle:
如下的表格描寫敘述了這些方法的詳情,和在整個活動生命週期中的位置:
Method——方法 | Description——詳情 | Killable?——是否可結束? | Next——下一步 | ||
---|---|---|---|---|---|
|
Called when the activity is first created. This is where you should do all of your normal static set up — create views, bind data to lists, and so on. This method is passed a Bundle object containing the activity's previous state, if that state was captured (see Saving Activity State, later). Always followed by
|
No 不可 |
onStart() |
||
|
Called after the activity has been stopped, just prior to it being started again. 活動被中止以後。又一次啓動以前被調用。 Always followed by |
No 不可 |
onStart() |
||
|
Called just before the activity becomes visible to the user. Followed by |
No 不可 |
onResume() or onStop() onResume() 或是onStop() |
||
|
Called just before the activity starts interacting with the user. At this point the activity is at the top of the activity stack, with user input going to it. Always followed by |
No 不可 |
onPause() |
||
|
Called when the system is about to start resuming another activity. This method is typically used to commit unsaved changes to persistent data, stop animations and other things that may be consuming CPU, and so on. It should do whatever it does very quickly, because the next activity will not be resumed until it returns. 系統要開始繼續其它活動時被調用。這種方法典型的使用方法是將爲保存的數據存入穩定存儲,中止動畫或其它佔用CPU的動做等等。這種方法中動做應儘快完畢。因爲完畢後,下一個活動纔會開始。 Followed either by |
Yes 可以 |
onResume() or onStop() |
||
|
Called when the activity is no longer visible to the user. This may happen because it is being destroyed, or because another activity (either an existing one or a new one) has been resumed and is covering it. 活動對用戶再也不可見時被調用。這樣的狀況通常發生在活動被銷燬時或者還有一個活動(已存在的或新啓動的)被繼續,而且覆蓋了這個活動。 Followed either by |
Yes 可以 |
onRestart() or onDestroy() |
||
|
Called before the activity is destroyed. This is the final call that the activity will receive. It could be called either because the activity is finishing (someone called on it), or because the system is temporarily destroying this instance of the activity to save space. You can distinguish between these two scenarios with the method.活動被銷燬以前被調用。這是活動接到的最後一個調用。當活動完畢以後(有些人調用 finish())或系統爲了節約空間將這個實例臨時銷燬 時會被調用。您應該可以看出和調用 方法之間的差異。 |
Yes 可以 |
nothing 無 |
Note the Killable column in the table above. It indicates whether or not the system can kill the process hosting the activity at any time after the method returns, without executing another line of the activity's code. Three methods (onPause()
, onStop()
, and onDestroy()
) are marked "Yes." Because onPause()
is the first of the three, it's the only one that's guaranteed to be called before the process is killed — onStop()
and onDestroy()
may not be. Therefore, you should use onPause()
to write any persistent data (such as user edits) to storage.
注意上邊的表格中Killable?——是否可結束?一欄。它表示了系統會不會 在方法動做結束後再也不執行活動的代碼就 結束承載着這個活動的進程。有三個方法(onPause()
,onStop()
和onDestroy()
)標誌着"Yes."。因爲onPause()
是這三個方法中第一個,因此他是惟一一個被贊成在進程被結束以前調用的方法——onStop()
和onDestroy()
則可能不行。因此,將數據(好比用戶改動信息)存入穩定存儲的過程應在onPause()
中完畢。
Methods that are marked "No" in the Killable column protect the process hosting the activity from being killed from the moment they are called. Thus an activity is in a killable state, for example, from the time onPause()
returns to the timeonResume()
is called. It will not again be killable until onPause()
again returns.
Killable?——是否可結束?一欄標註着「No」的方法保護了其所在進程在這種方法調用之時起不被結束。就是說,好比在onPause()
方法完畢以後到onResume()
被調用以前這段時間以內。進程是可能被結束的。而後到下一次onPause()
完畢以前,進程是不可結束的。
As noted in a later section, Processes and lifecycle, an activity that's not technically "killable" by this definition might still be killed by the system — but that would happen only in extreme and dire circumstances when there is no other recourse.
像下邊Processes and lifecycle章節提到的。上邊定義的技術上講不會被結束的活動仍是有可能被系統結束的——但僅僅是在極端的沒有一點其它資源時纔會發生。
When the system, rather than the user, shuts down an activity to conserve memory, the user may expect to return to the activity and find it in its previous state.
當系統,而不是用戶,爲了釋放內存而關閉這個活動時。用戶固然但願再次進入這個活動時狀態仍是以前的狀態。
To capture that state before the activity is killed, you can implement an
method for the activity. Android calls this method before making the activity vulnerable to being destroyed — that is, before onSaveInstanceState()
onPause()
is called. It passes the method a Bundle
object where you can record the dynamic state of the activity as name-value pairs. When the activity is again started, the Bundle is passed both to onCreate()
and to a method that's called afteronStart()
,
, so that either or both of them can recreate the captured state.onRestoreInstanceState()
截獲活動被結束以前的狀態。您需要實現活動的
onSaveInstanceState()方法。Android會在使這個活動實例接近銷燬條件以前調用這種方法——就是說,onPause()
調用以前。Android傳遞給這種方法一個Bundle對象,從而您可以以 名稱-值 對的形式記錄這個活動的動態狀態。
當這個活動再次開啓之時。Bundle對象會傳遞給 onCreate()
和 onStart()
以後調用的一個方法——
onRestoreInstanceState() ,而後。您可以用這兩個中任一個重建 處於截獲的狀態的 活動。
Unlike onPause()
and the other methods discussed earlier, onSaveInstanceState()
and onRestoreInstanceState()
are not lifecycle methods. They are not always called. For example, Android calls onSaveInstanceState()
before the activity becomes vulnerable to being destroyed by the system, but does not bother calling it when the instance is actually being destroyed by a user action (such as pressing the BACK key). In that case, the user won't expect to return to the activity, so there's no reason to save its state.
不像onPause()
和前面講的其它方法,onSaveInstanceState()
和onRestoreInstanceState()
不是生命週期方法。他們不是總會被調用。好比。Android在活動合乎有可能被系統銷燬的條件的時候會調用onSaveInstanceState()
。但是在用戶發出動做(好比按下BACK鍵)將實例實際銷燬時不會調用。
但在這樣的狀況下。用戶也沒有但願回到這個活動,所以也沒有保存狀態的必要。
Because onSaveInstanceState()
is not always called, you should use it only to record the transient state of the activity, not to store persistent data. Use onPause()
for that purpose instead.
因爲onSaveInstanceState()
不是必定會被調用,所以您僅僅能用它保存過渡狀態,而不能用來保存穩定數據。如要保存穩定數據。請使用onPause()
。
When one activity starts another, they both experience lifecycle transitions. One pauses and may stop, while the other starts up. On occasion, you may need to coordinate these activities, one with the other.
當一個活動開啓了還有一個活動時。這兩個活動都經歷了生命週期的變化。就一個活動暫停或中止,新一個活動開啓。有些狀況下,您可能需要協調這些活動。
The order of lifecycle callbacks is well defined, particularly when the two activities are in the same process:
生命週期回調方法的順序已經定義好,特別是當這兩個活動在同一個進程中:
onPause()
method is called.——當前的活動的onPause()
方法被調用·。onCreate()
, onStart()
, and onResume()
methods are called in sequence.——而後,新一個活動的onCreate()
、onStart()
和onResume()
方法依次被調用。onStop()
method is called.——而後。假設舊一個活動在屏幕上再也不可見。他的onStop()
方法會被調用。A service can be used in two ways:
服務可用於如下兩種方式:
Context.startService()
and stopped by calling Context.stopService()
. It can stop itself by callingService.stopSelf()
or Service.stopSelfResult()
. Only one stopService()
call is needed to stop the service, no matter how many times startService()
was called.——他可以啓動並執行指導什麼將它中止或她本身中止。在這樣的模式中。他經過調用Context.startService()
開啓,經過調用Context.stopService()
中止。服務能經過調用Service.stopSelf()
或Service.stopSelfResult()
中止本身。中止一個服務僅僅需一個stopService()
的調用,無論用了多少次startService()
。
It can be operated programmatically using an interface that it defines and exports. Clients establish a connection to the Service object and use that connection to call into the service. The connection is established by calling
, and is closed by calling Context.bindService()
. Multiple clients can bind to the same service. If the service has not already been launched, Context.unbindService()
bindService()
can optionally launch it. ——對服務可以使用他定義和導出的接口進行 編程性的操做。client創建一個到Service對象的鏈接,而後使用這個鏈接對服務進行請求。鏈接使用Context.bindService()
創建。使用Context.unbindService()
斷開。多個client可以綁定到一個服務。假設服務還未被啓動,可用bindService()
啓動它。
The two modes are not entirely separate. You can bind to a service that was started with startService()
. For example, a background music service could be started by calling startService()
with an Intent object that identifies the music to play. Only later, possibly when the user wants to exercise some control over the player or get information about the current song, would an activity establish a connection to the service by calling bindService()
. In cases like this,stopService()
will not actually stop the service until the last binding is closed.
這兩個方式不是全然分開的。
您可以綁定到一個使用startService()
啓動的服務上。好比,一個後臺的音樂播放服務可以調用startService()
並傳遞一個包括識別要播放的音樂的意圖來啓動。片刻後,當 用戶想對播放器進行控制或獲取正在播放的音樂的信息 時,您可能就要需要一個活動調用bindService()
來創建到這個服務的鏈接。像這個狀況,stopService()
不會真的中止服務,直到最後一個綁定解開。
Like an activity, a service has lifecycle methods that you can implement to monitor changes in its state. But they are fewer than the activity methods — only three — and they are public, not protected:
像活動同樣。服務也有您可以對其進行實現以監視服務狀態的生命週期方法。但是比活動的少——僅僅有三個——而且是公共的。而不是受保護的:
void onCreate()
void onStart(Intent intent)
void onDestroy()
By implementing these methods, you can monitor two nested loops of the service's lifecycle:
實現後,您可以監控服務的這兩個生命週期嵌套循環:
onCreate()
is called and the time onDestroy()
returns. Like an activity, a service does its initial setup in onCreate()
, and releases all remaining resources in onDestroy()
. For example, a music playback service could create the thread where the music will be played in onCreate()
, and then stop the thread in onDestroy()
.——服務的整個存在時間是從onCreate()
被調用到onDestroy()
完畢。像活動同樣,服務在onCreate()
被調用時進行初始化設置,在onDestroy()
中完畢佔有的資源的釋放。好比,音樂播放服務會在onCreate()
中爲音樂的播放創建新的線程,而後在onDestroy()
中結束線程。
The active lifetime of a service begins with a call to
. This method is handed the Intent object that was passed to onStart()
startService()
. The music service would open the Intent to discover which music to play, and begin the playback.——服務的動做時間是從onStart()
的調用開始的。
傳遞給startService()
的Intent對象又被傳遞給這種方法。音樂播放服務會打開這個意圖找到要播放哪一個歌曲,而後開始播放。
There's no equivalent callback for when the service stops — no onStop()
method.
服務沒有像活動的中止時的回調方法——就是沒有onStop()
方法。
The onCreate()
and onDestroy()
methods are called for all services, whether they're started by
or Context.startService()
. However, Context.bindService()
onStart()
is called only for services started by startService()
.
無論服務是否由Context.startService()
或Context.bindService()
啓動。onCreate()
和onDestroy()
方法都會被調用。但是,系統僅僅會爲由startService()
啓動的服務調用onStart()
。
If a service permits others to bind to it, there are additional callback methods for it to implement:
假設服務贊成別人綁定到他。您還需要實現如下幾個回調方法:
IBinder onBind(Intent intent)
boolean onUnbind(Intent intent)
void onRebind(Intent intent)
The
callback is passed the Intent object that was passed to onBind()
bindService
and
is handed the intent that was passed to onUnbind()
unbindService()
. If the service permits the binding, onBind()
returns the communications channel that clients use to interact with the service. The onUnbind()
method can ask for
to be called if a new client connects to the service.onRebind()
onBind()
方法得到傳遞給bindService
的Intent對象,onUnbind()
方法得到傳遞unbindService()
給的Intent對象假設服務贊成綁定。onBind()
返回client用以和服務交互的信道。
onUnbind()
方法可以在新的客戶鏈接到服務時讓系統調用onRebind()
。
The following diagram illustrates the callback methods for a service. Although, it separates services that are created via startService
from those created by bindService()
, keep in mind that any service, no matter how it's started, can potentially allow clients to bind to it, so any service may receive onBind()
and onUnbind()
calls.
如下的圖表演示了服務的回調方法。
儘管,使用startService
和bindService()
開啓的服務稍有不一樣,但是請記住,所有服務。無論是怎麼啓動的,通常都會贊成服務綁定到他,所以所有的服務都有可能收到onBind()
和onUnbind()
調用。
A broadcast receiver has single callback method:
廣播接收器僅僅有一個回調方法:
void onReceive(Context curContext, Intent broadcastMsg)
When a broadcast message arrives for the receiver, Android calls its
method and passes it the Intent object containing the message. The broadcast receiver is considered to be active only while it is executing this method. When onReceive()
onReceive()
returns, it is inactive.
廣播消息到達接收器時。Android 調用他的
onReceive()方法而且將一個包括有廣播信息的Intent對象傳遞給這種方法。
咱們以爲廣播接收器僅僅有在執行這種方法時是被激活的。onReceive()
方法完畢以後。他就再也不活動。
A process with an active broadcast receiver is protected from being killed. But a process with only inactive components can be killed by the system at any time, when the memory it consumes is needed by other processes.
一個承載着激活的廣播接收者的進程是不會被結束的。但是僅僅有不活動的接收者組件的進程可能被系統 在別的進程需要他所佔用的內存時 隨時結束。
This presents a problem when the response to a broadcast message is time consuming and, therefore, something that should be done in a separate thread, away from the main thread where other components of the user interface run. IfonReceive()
spawns the thread and then returns, the entire process, including the new thread, is judged to be inactive (unless other application components are active in the process), putting it in jeopardy of being killed. The solution to this problem is for onReceive()
to start a service and let the service do the job, so the system knows that there is still active work being done in the process.
當對廣播信息的響應是一個耗時的事,而後,所以應該單獨給他一個線程執行。而不是在其它組件所在的與用戶交互的線程中時,問題就出現了。
假設建立了新的線程而後在新線程中執行。整個進程,包括新線程 就都被以爲是不活動的了(除非進程中有其它活動的應用程序組件),而且有被結束的危急。解決辦法是,讓啓動一個服務。而後讓服務作這個耗時的事,而後系統就知道了進程中還有活動的正在作的事。
The next section has more on the vulnerability of processes to being killed.
下一節講了不少其它有關進程被結束的easy程度。
The Android system tries to maintain an application process for as long as possible, but eventually it will need to remove old processes when memory runs low. To determine which processes to keep and which to kill, Android places each process into an "importance hierarchy" based on the components running in it and the state of those components. Processes with the lowest importance are eliminated first, then those with the next lowest, and so on. There are five levels in the hierarchy. The following list presents them in order of importance:
Android系統試圖將應用程序的進程保持最長的時間,但是終於當內存不足時,仍是需要將不用的進程結束掉。爲了推斷哪些進程該結束,哪些不應, Android將每一個進程依照其中執行的組件和組件的狀態 排放到一個「重要程度排行表」中。最不重要的最早結束,而後是次不重要的,依此類推。
「重要程度排行表」中有五層重要程度。如下的表按重要程度順序列出了他們:
進程有下列狀況的,即認定爲前臺進程:
onResume()
method has been called).——正在執行一個用戶正與之交互的活動(即活動的
onResume()方法被調用了)It hosts a service that's bound to the activity that the user is interacting with.——承載了一個 用戶正在與之交互的活動所屬的 服務。
It has a Service
object that's executing one of its lifecycle callbacks (
, onCreate()
, or onStart()
).——承載着一個正在執行其生命週期回調方法(onDestroy()
onCreate(),
onStart()或
onDestroy())的Service對象。
It has a BroadcastReceiver
object that's executing its
method.——承載了一個正在執行其onReceive()
onReceive()方法的BroadcastReceiver
對象。
Only a few foreground processes will 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.——任一時刻僅僅會有很是少的前臺進程存在。結束他們是沒有辦法的辦法——僅僅有當內存不足到他們都無法執行了。一般狀況下,到了這樣的情況,設備就到了內存分頁狀態。結束一些前臺進程是爲了保持用戶界面的響應。
A visible process is one 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 holds:——可見進程是沒有不論什麼前臺組件。但是依然可以被用戶看見的進程。進程有下列狀況之中的一個的,即認定爲前臺進程:
onPause()
method has been called). This may occur, for example, if the foreground activity is a dialog that allows the previous activity to be seen behind it.——承載着不在前臺的活動,但是活動依然能被用戶看到(活動的
onPause()方法被調用了)。好比當前臺活動是一個沒有全然蓋住舊一個活動對話框時這樣的狀況就可能發生。It hosts a service that's bound to a visible activity.——承載了一個屬於可見活動的服務。
A visible process is considered extremely important and will not be killed unless doing so is required to keep all foreground processes running.——可見進程也是極爲重要的。除非結束可見進程是爲了保持前臺進程的執行。不然可見進程是不會被結束的。
A service process is one that is running a service that has been started with the
method and that 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 an mp3 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()
startService()方法啓動的而且不在前兩種所述狀況中的服務的 進程。
儘管服務進程不與不論什麼用戶可見部分直接相連。但他們通常是在作一些用戶關心的事(好比在後臺播放音樂或從網上下載數據),因此除非內存不足以盛放前臺和可見進程,系統是不會結束服務進程的。
A background process is one holding an activity that's not currently visible to the user (the Activity object's
method has been called). These processes have no direct impact on the user experience, and can be killed 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 captures its current state, killing its process will not have a deleterious effect on the user experience.——後臺進程是承載眼下用戶不可見的活動(Activity的onStop()
onStop()方法被調用後)的進程。
後臺進程不直接影響用戶體驗,而且隨時可以結束以回收供前臺進程、可見進程和服務進程使用。
一般同一時間會有很是多正在執行的後臺進程,所以他們被存放在LRU(近期使用過的)列表中以保證最後含實用戶最後使用的活動的進程是最後被結束的。假設活動正確地實現了其生命週期方法截獲了當前狀態,那麼結束他所在進程不會對用戶體驗有壞的影響。
An empty process is one that doesn't hold any active application components. The only reason to keep such a process around is as a cache 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 will be ranked as a visible process, not a service process.
Android依據在進程中正在活動的組件的重要程度 將進程排在他能處在的最高級。好比,假設一個進程承載了一個服務和一個可見進程。那麼此進程就被排爲可見進程,而不是服務進程。
In addition, a process's ranking may 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 will always be considered at least as important as process B.
另外,假設有其它進程依賴於此進程。那此進程的排位會上升。一個正服務於其它進程 的進程的排位不會低於他服務於的進程的排位。好比,進程A中的一個內容提供者正在爲一個進程B中的客戶服務,或者假設進程A中的服務屬於進程B的一個組件。那麼以爲進程A至少與B重要性一樣。
Because a process running a service is ranked higher than one with background activities, an activity that initiates a long-running operation might do well to start a service for that operation, rather than simply spawn a thread — particularly if the operation will likely outlast the activity. Examples of this are playing music in the background and uploading a picture taken by the camera to a web site. Using a service guarantees that the operation will have at least "service process" priority, regardless of what happens to the activity. As noted in the Broadcast receiver lifecycle section earlier, this is the same reason that broadcast receivers should employ services rather than simply put time-consuming operations in a thread.
因爲執行着服務的進程排位比執行着後臺活動的進程高。所以相比於僅僅是簡單的新建一個線程進行耗時的操做——特別是進行可能會超過活動生命時間的操做,新建一個服務進行那項操做使您更好的選擇。好比在後臺播放音樂和拍照後將照片上傳到網上。使用服務確保了操做會持續「服務進程」那麼長的時間。無論活動發生了什麼。就像上邊Broadcast receiver lifecycle章節提到的那樣。這也是廣播server應該藉助一個服務進行耗時的操做,而不是將其簡單地放到新的線程中。
From:
developer.android.com/guide/components/fundamentals.html
www.cnitblog.com/seedshopezhong/archive/2010/03/29/64914.html