blob: e3ce58f7770de6e00cff07095e9c8cbf6880ffd8 [file] [log] [blame]
page.title=工作和返回堆疊
parent.title=Activity
parent.link=activities.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>本文件內容</h2>
<ol>
<li><a href="#ActivityState">儲存 Activity 狀態</a></li></li>
<li><a href="#ManagingTasks">管理工作</a>
<ol>
<li><a href="#TaskLaunchModes">定義啟動模式</a></li>
<li><a href="#Affinities">處理親和性</a></li>
<li><a href="#Clearing">清除返回堆疊</a></li>
<li><a href="#Starting">開始工作</a></li>
</ol>
</li>
</ol>
<h2>文章</h2>
<ol>
<li><a href="http://android-developers.blogspot.com/2010/04/multitasking-android-way.html"> Android 的多工作業方式
</a></li>
</ol>
<h2>另請參閱</h2>
<ol>
<li><a href="{@docRoot}design/patterns/navigation.html">Android 設計:導覽
</a></li>
<li><a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;} 宣示說明元素
</a></li>
<li><a href="{@docRoot}guide/components/recents.html">總覽畫面</a></li>
</ol>
</div>
</div>
<p>一個應用程式通常包含多個 <a href="{@docRoot}guide/components/activities.html">Activity</a>。每個 Activity 應根據使用者可執行的特定動作類型加以設計,且要能啟動其他 Activity。
例如,電子郵件應用程式可能會有一個可顯示新訊息清單的 Activity。
當使用者選擇一則訊息,會開啟新的 Activity 以檢視該訊息。</p>
<p>Activity 甚至可啟動裝置上其他應用程式的 Activity。例如,如果您的應用程式想要傳送一封電子郵件訊息,您可以定義一個意圖以執行「傳送」動作並包含一些資料,像是電子郵件地址和訊息。
其他應用程式中宣告處理此意圖類型的 Activity 就會開啟。
在這種情況下,意圖就是要傳送電子郵件,因此電子郵件應用程式會啟動「撰寫」Activity (如果有多個 Activity 支援相同的意圖,則系統會讓使用者選擇要使用的 Activity)。
電子郵件傳送後,您的 Activity 就會繼續,並將電子郵件 Activity 視為您應用程式的一部分。
雖然 Activity 可能來自不同的應用程式,但 Android 會將兩個 Activity 放在相同的工作中,以維護使用者體驗的流暢性。
<em></em></p>
<p>工作是執行特定工作時,與使用者互動的 Activity 集合。
Activity 會在堆疊 (返回堆疊<em></em>) 中依照每個 Activity 開啟的順序加以排列。
</p>
<!-- SAVE FOR WHEN THE FRAGMENT DOC IS ADDED
<div class="sidebox-wrapper">
<div class="sidebox">
<h3>Adding fragments to a task's back stack</h3>
<p>Your activity can also include {@link android.app.Fragment}s to the back stack. For example,
suppose you have a two-pane layout using fragments, one of which is a list view (fragment A) and the
other being a layout to display an item from the list (fragment B). When the user selects an item
from the list, fragment B is replaced by a new fragment (fragment C). In this case, it might be
desireable for the user to navigate back to reveal fragment B, using the <em>Back</em> button.</p>
<p>In order to add fragment B to the back stack so that this is possible, you must call {@link
android.app.FragmentTransaction#addToBackStack addToBackStack()} before you {@link
android.app.FragmentTransaction#commit()} the transaction that replaces fragment B with fragment
C.</p>
<p>For more information about using fragments and adding them to the back stack, see the {@link
android.app.Fragment} class documentation.</p>
</div>
</div>
-->
<p>裝置主螢幕是大多數工作開始的地方。當使用者輕觸應用程式啟動組件上的某個圖示 (或主螢幕上的捷徑 ) 時,應用程式工作會移到前景。
如果應用程式沒有工作 (最近未使用應用程式),則會建立新的工作,且該應用程式的「主要」Activity 會以堆疊中的根 Activity 形式開啟。
</p>
<p>當目前的 Activity 啟動另一個 Activity 時,會將新的 Activity 推到堆疊的頂端並取得焦點。
之前的 Activity 會留在堆疊中,但已停止。Activity 停止後,系統會保留其使用者介面的目前狀態。
當使用者按下 [返回] 按鈕<em></em>,會將目前的 Activity 從堆疊頂端推出 (Activity 已終結),並繼續進行之前的 Activity (還原其 UI 之前的狀態)。
堆疊中的 Activity 不會重新整理,只會從堆疊推入和推出 &mdash; 由目前 Activity 啟動時推入堆疊,而當使用者使用 [返回] 按鈕離開時推出堆疊。<em></em>
因此,返回堆疊會以「後進先出」的物件結構進行運作。
圖 1 透過時間軸將此行為視覺化,以時間軸顯示 Activity 間的進度以及每個時間點的目前返回堆疊。
</p>
<img src="{@docRoot}images/fundamentals/diagram_backstack.png" alt="" />
<p class="img-caption"><strong>圖 1.</strong>顯示工作中每個新 Activity 如何將項目新增到返回堆疊。
當使用者按下 [返回] 按鈕,目前的 Activity 將會終結,而之前的 Activity 則會繼續進行。<em></em>
</p>
<p>如果使用者持續按下 [返回]<em></em>,則會持續推出堆疊中的每個 Activity 以顯示之前的 Activity,直到使用者返回主螢幕 (或到工作開始時執行的 Activity)。
當堆疊中的 Activity 全部移除後,工作將不再存在。</p>
<div class="figure" style="width:287px">
<img src="{@docRoot}images/fundamentals/diagram_multitasking.png" alt="" /> <p
class="img-caption"><strong>圖 2.</strong>兩個工作:工作 B 在前景收到使用者互動,而工作 A 在背景等待繼續。
</p>
</div>
<div class="figure" style="width:215px">
<img src="{@docRoot}images/fundamentals/diagram_multiple_instances.png" alt="" /> <p
class="img-caption"><strong>圖 3.</strong>單一 Activity 會具現化很多次。</p>
</div>
<p>工作是一個緊密結合的單位,當使用者開始新的工作時可以移到「背景」,或透過 [首頁] 按鈕前往主螢幕。<em></em>
在背景時,工作中的所有 Activity 都會停止,但該工作的返回堆疊會保留下來 &mdash; 該工作純粹失去焦點,由另一個工作取而代之,如圖 2 所示。
之後,工作可以返回「前景」,讓使用者繼續未完成的工作。
例如,假設目前的工作 (工作 A) 的堆疊中有三個 Activity &mdash; 兩個位於目前的 Activity 下。
使用者按下 [首頁] 按鈕,<em></em>然後從應用程式啟動新的應用程式。
當主螢幕出現時,工作 A 會移到背景。
新的應用程式啟動時,系統會啟動該應用程式的工作 (工作 B),該應用程式會有自己的 Activity 堆疊。
與該應用程式互動之後,使用者會再次回到首頁,並選取原來啟動工作 A 的應用程式。現在,工作 A 移到了前景 &mdash; 堆疊中的三個 Activity 全部保持不變,而堆疊中最頂端的 Activity 則會繼續進行。
此時,使用者也能切換回工作 B,前往首頁並選取啟動該工作的應用程式圖示 (或從<a href="{@docRoot}guide/components/recents.html">總覽畫面</a>選取應用程式工作)。這是在 Android 執行多工作業的範例。
</p>
<p class="note"><strong>注意:</strong>背景可以一次執行多個工作。
不過,如果使用者同時執行多個背景工作,系統可能會開始終結背景 Activity 以復原記憶體,導致 Activity 狀態遺失。
請參閱下列有關 <a href="#ActivityState">Activity 狀態</a>的章節。
</p>
<p>由於返回堆疊中的 Activity 不會重新整理,如果您的應用程式允許使用者從一個以上的 Activity 中啟動特定 Activity,則會建立該 Activity 的新執行個體並推入堆疊 (而不會將 Activity 任何之前的執行個體移到最頂端)。
因此,您應用程式中的一個 Activity 可能會具現化很多次 (甚至來自不同的工作),如圖 3 所示。
也因為這樣,如果使用者使用 [返回] 按鈕瀏覽之前的資訊,Activity 的每個執行個體會依開啟的順序顯示<em></em> (每個會有自己的 UI 狀態)。
不過,如果您不希望 Activity 具現化一次以上,則可以修改這個行為。
如需詳細步驟,請參閱下文的<a href="#ManagingTasks">管理工作</a>。</p>
<p>摘要說明 Activity 和工作的預設行為:</p>
<ul>
<li>當 Activity A 啟動 Activity B,Activity A 會停止,但系統會保留其狀態(例如捲軸位置和輸入表單的文字)。
如果使用者在 Activity B 按下 [返回] 按鈕,<em></em>Activity A 的狀態會復原並繼續執行。
</li>
<li>當使用者按下 [首頁] 按鈕離開工作,<em></em>目前的 Activity 會停止且其工作會移到背景。
系統會保留工作中所有 Activity 的狀態。如果使用者稍後選取啟動工作的啟動組件圖示繼續執行工作,工作會移到前景並在堆疊頂端繼續執行 Activity。
</li>
<li>如果使用者按下 [返回] 按鈕<em></em>,會將目前的 Activity 從堆疊推出並終結。
堆疊中之前的 Activity 會繼續進行。Activity 終結後,系統將不會保留 Activity 的狀態。
<em></em></li>
<li>Activity 可以具現化很多次,即使來自其他工作也一樣。</li>
</ul>
<div class="note design">
<p><strong>導覽設計</strong></p>
<p>如需應用程式導覽如何在 Android 運作的詳細資訊,請參閱 Android 設計的<a href="{@docRoot}design/patterns/navigation.html">導覽</a>指南。</p>
</div>
<h2 id="ActivityState">儲存 Activity 狀態</h2>
<p>如上所述,系統的預設行為會在 Activity 停止時保留 Activity 的狀態。
如此一來,當使用者瀏覽之前的 Activity 時,其使用者介面的顯示方式將與離開時一樣。
不過,您可以 &mdash; 也<strong>應該</strong> &mdash; 使用回呼方法主動保留 Activity 的狀態,以防止 Activity 遭到終結且必須重新建立的情況。
</p>
<p>如果系統停止您其中一個 Activity (例如,當新的 Activity 開始或工作移到背景),當系統需要復原系統記憶體時,可能會完全終結該 Activity。
發生這種情況時,與 Activity 狀態相關的資訊都將遺失。如果發生這種情況,系統仍然知道該 Activity 位於返回堆疊中,但是當 Activity 移到堆疊頂端時,系統必須重新建立該 Activity (而不是繼續執行)。
如果不想讓使用者的工作遺失,您應該在 Activity 中實作 {@link android.app.Activity#onSaveInstanceState onSaveInstanceState()} 回呼方法,主動保留該工作。
</p>
<p>如需儲存 Activity 狀態的詳細資訊,請參閱 <a href="{@docRoot}guide/components/activities.html#SavingActivityState">Activity</a> 文件。
</p>
<h2 id="ManagingTasks">管理工作</h2>
<p>如上所述,Android 管理工作和返回堆疊的方式 &mdash; 將連續啟動的所有 Activity 放在相同的工作及「後進先出」堆疊中 &mdash; 對大多數應用程式而言非常好用,而且您不需擔心 Activity 與工作關聯的方式或它們如何存在於返回堆疊中。
不過,您也許會想中斷一般的行為。
您或許會希望應用程式的 Activity 可以在啟動時開始一個新的工作 (而不是放入目前的工作中);或者當您啟動一個 Activity 時,您可能會想使用其現有的執行個體 (而不是在返回堆疊頂端建立新的執行個體);又或者當使用者離開工作時,您想要清除返回堆疊中的所有 Activity,只留下根 Activity。
</p>
<p>如要執行這些工作及更多工作,您可以使用 <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a> 宣示說明元素中的屬性,以及您傳送到 {@link android.app.Activity#startActivity startActivity()} 之意圖中的旗標。
</p>
<p>就這個情況而言,您可以使用的主要 <a href="{@docRoot}guide/topics/manifest/activity-element.html">
{@code &lt;activity&gt;}</a> 屬性包括:</p>
<ul class="nolist">
<li><a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">
{@code taskAffinity}</a></li>
<li><a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">
{@code launchMode}</a></li>
<li><a href="{@docRoot}guide/topics/manifest/activity-element.html#reparent">
{@code allowTaskReparenting}</a></li>
<li><a href="{@docRoot}guide/topics/manifest/activity-element.html#clear">
{@code clearTaskOnLaunch}</a></li>
<li><a href="{@docRoot}guide/topics/manifest/activity-element.html#always">
{@code alwaysRetainTaskState}</a></li>
<li><a href="{@docRoot}guide/topics/manifest/activity-element.html#finish">
{@code finishOnTaskLaunch}</a></li>
</ul>
<p>而您可以使用的主要意圖旗標包括:</p>
<ul class="nolist">
<li>{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}</li>
<li>{@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP}</li>
<li>{@link android.content.Intent#FLAG_ACTIVITY_SINGLE_TOP}</li>
</ul>
<p>在以下各節中,您將瞭解如何使用這些宣示說明屬性和意圖旗標,定義 Activity 與工作關聯的方式以及它們在返回堆疊中的行為。
</p>
<p>同時,還會分開討論工作與 Activity 如何在總覽畫面表示和進行管理。
請參閱<a href="{@docRoot}guide/components/recents.html">總覽畫面</a>以取得詳細資訊。
一般而言,您應該允許系統定義如何在總覽畫面中呈現工作與 Activity,而且不需要修改此行為。
</p>
<p class="caution"><strong>注意:</strong>大多數應用程式不應中斷 Activity 和工作的預設行為:
如果您判斷修改 Activity 的預設行為是必要的,請謹慎小心並記得測試啟動期間 Activity 的可用性,以及使用 [返回] 按鈕從其他 Activity 和工作瀏覽到此 Activity 的情況。請記得測試可能會與使用者預期的行為衝突的瀏覽行為。<em></em>
</p>
<h3 id="TaskLaunchModes">定義啟動模式</h3>
<p>啟動模式可讓您定義 Activity 的新執行個體與目前工作關聯的方式。
您可用兩種方法定義不同的啟動模式:</p>
<ul class="nolist">
<li><a href="#ManifestForTasks">使用宣示說明檔案</a>
<p>當您在宣示說明檔案中宣告 Activity 時,您可以指定 Activity 啟動時該如何與工作關聯。
</li>
<li><a href="#IntentFlagsForTasks">使用意圖旗標</a>
<p>當您呼叫 {@link android.app.Activity#startActivity startActivity()} 時,您可以在 {@link android.content.Intent} 包含一個旗標,宣告新 Activity 應如何 (或是否) 與目前的工作關聯。
</p></li>
</ul>
<p>因此,如果 Activity A 啟動 Activity B,Activity B 可以在其宣示說明中定義它應如何與目前的工作 (如果有) 關聯,而且 Activity A 也能要求 Activity B 應如何與目前的工作關聯。
如果這兩個 Activity 皆定義 Activity B 應如何與工作關聯,相較於 Activity B 的要求 (如宣示說明中所定義),會優先採用 Activity A 的要求 (如意圖中所定義)。
</p>
<p class="note"><strong>注意:</strong>某些宣示說明檔案中提供的啟動模式可能沒有對應的意圖旗標,同樣地,某些意圖旗標提供的啟動模式無法在宣示說明中定義。
</p>
<h4 id="ManifestForTasks">使用宣示說明檔案</h4>
<p>當您在宣示說明檔案中宣告 Activity 時,您可以使用 <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a> 元素的 <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code
launchMode}</a> 屬性,指定 Activity 應如何與工作關聯。
</p>
<p><a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code
launchMode}</a> 屬性可指定應如何將 Activity 啟動至工作內的指示。
您可以為
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">launchMode</a></code> 屬性指定四種不同的啟動模式:
</p>
<dl>
<dt>{@code "standard"} (預設模式)</dt>
<dd>預設。系統在啟動 Activity 的工作中建立新的執行個體,並將意圖路由至該處。
Activity 可以具現化很多次,每個執行個體可屬於不同的工作,而且一個工作可以有多個執行個體。
</dd>
<dt>{@code "singleTop"}</dt>
<dd>如果 Activity 的執行個體已經出現在目前工作的頂端,系統會透過呼叫其 {@link
android.app.Activity#onNewIntent onNewIntent()} 方法,將意圖路由至該執行個體,而不是建立新的 Activity 執行個體。
Activity 可以具現化很多次,每個執行個體可屬於不同的工作,而且一個工作可以有多個執行個體 (但僅限於返回堆疊頂端的 Activity 不是現有的 Activity 執行個體時<em></em>)。
<p>例如,假設工作的返回堆疊包含根 Activity A 及 Activity B、C 及在最頂端的 D (堆疊為 A-B-C-D;D 在最頂端)。
類型 D Activity 的意圖抵達。
如果 D 有預設的 {@code "standard"} 啟動模式,則會啟動新的類別執行個體,且堆疊會變成 A-B-C-D-D。不過,如果 D 啟動模式為 {@code "singleTop"},D 的現有執行個體會透過 {@link
android.app.Activity#onNewIntent onNewIntent()} 接收意圖,這是因為它位於堆疊的最頂端 &mdash; 堆疊會維持 A-B-C-D。不過,如果類型 B Activity 的意圖抵達,則 B 的新執行個體會新增到堆疊中,即使其啟動模式為 {@code "singleTop"} 也是如此。
</p>
<p class="note"><strong>注意:</strong>建立新的 Activity 執行個體之後,使用者可按下 [返回]<em></em> 按鈕,返回之前的 Activity。
但是,如果處理新意圖的是現有的 Activity 執行個體,則使用者無法按下 [返回]<em></em> 按鈕回到新意圖抵達 {@link android.app.Activity#onNewIntent
onNewIntent()} 之前的 Activity 狀態。
</p>
</dd>
<dt>{@code "singleTask"}</dt>
<dd>系統會建立新的工作並在新工作的根目錄將 Activity 具現化。不過,如果 Activity 的執行個體已經出現在其他工作中,系統會透過呼叫其 {@link
android.app.Activity#onNewIntent onNewIntent()} 方法,將意圖路由至現有的執行個體,而不是建立新的執行個體。
一次只能有一個 Activity 執行個體。
<p class="note"><strong>注意:</strong>雖然 Activity 是在新工作中啟動,使用者仍可使用 [返回] 按鈕返回之前的 Activity。
<em></em></p></dd>
<dt>{@code "singleInstance"}。</dt>
<dd>與 {@code "singleTask"} 一樣,差別在於系統不會將任何其他 Activity 啟動至保留執行個體的工作中。
Activity 一律是其工作的唯一成員;使用此項目啟動的任何 Activity 會在個別的工作中開啟。
</dd>
</dl>
<p>另外一個例子,Android 瀏覽器應用程式宣告網頁瀏覽器 Activity 應永遠在自己的工作中開啟 &mdash; 透過在 <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a> 元素指定 {@code singleTask} 啟動模式。
這表示如果您的應用程式發出開啟 Android 瀏覽器的意圖,其 Activity 不會與您的應用程式放在同一個工作中。<em></em>
而是會為瀏覽器啟動新的工作,或者如果瀏覽器已經有工作在背景執行,會將該工作帶出來處理新的意圖。
</p>
<p>無論 Activity 在新工作啟動或與啟動該 Activity 之 Activity 的相同工作中啟動,使用者都能使用 [返回] 按鈕返回之前的 Activity。<em></em>
不過,如果您啟動指定 {@code singleTask} 啟動模式的 Activity,如果該 Activity 的執行個體存在於背景工作中,則該工作會整個移到前景。
此時,返回堆疊現在包含已帶出且位於堆疊頂端之工作的所有 Activity。
圖 4 說明這種類型的情況。</p>
<img src="{@docRoot}images/fundamentals/diagram_backstack_singletask_multiactivity.png" alt="" />
<p class="img-caption"><strong>圖 4.</strong>顯示含有啟動模式 "singleTask" 的 Activity 如何新增到返回堆疊。
如果 Activity 已經是背景工作的一部份且有自己的返回堆疊,則整個返回堆疊都會帶出來,位於目前工作的最頂端。
</p>
<p>如要進一步瞭解如何使用宣示說明檔案中的啟動模式,請參閱 <code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code> 元素,其中會有 {@code launchMode} 屬性和可接受值的詳細說明。
</p>
<p class="note"><strong>注意:</strong>您使用 <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a> 屬性指定的 Activity 行為可被啟動 Activity 之意圖所含的旗標所覆寫,如下一節所述。
</p>
<h4 id="#IntentFlagsForTasks">使用意圖旗標</h4>
<p>啟動 Activity 時,您可以在傳送到 {@link
android.app.Activity#startActivity startActivity()} 的意圖中包含旗標,以修改 Activity 及其工作的預設關聯。
您可以用來修改預設行為的旗標包括:
</p>
<p>
<dt>{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}</dt>
<dd>在新工作中啟動 Activity。如果工作已為您目前啟動的 Activity 執行,該工作會移到前景並復原至上個狀態,而且 Activity 會在 {@link android.app.Activity#onNewIntent onNewIntent()} 收到新的意圖。
<p>這會產生與 {@code "singleTask"} <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a> 值相同的行為,如上節所述。
</p></dd>
<dt>{@link android.content.Intent#FLAG_ACTIVITY_SINGLE_TOP}</dt>
<dd>如果現在正在啟動的 Activity 是目前的 Activity (位於返回堆疊的頂端),則現有執行個體會收到 {@link android.app.Activity#onNewIntent onNewIntent()} 呼叫,而不會建立新的 Activity 執行個體。
<p>這會產生與 {@code "singleTop"} <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a> 值相同的行為,如上節所述。
</p></dd>
<dt>{@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP}</dt>
<dd>如果正在啟動的 Activity 已在目前的工作中執行,則不會啟動新的 Activity 執行個體,而是會終結位於其上方的所有其他 Activity,且此意圖會透過 {@link android.app.Activity#onNewIntent onNewIntent()} 傳送到繼續執行的 Activity 執行個體 (現在位於頂端)。
<p>沒有任何 <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a> 屬性值可以產生此行為。
</p>
<p>{@code FLAG_ACTIVITY_CLEAR_TOP} 最常與 {@code FLAG_ACTIVITY_NEW_TASK} 搭配使用。
一起使用時,這些旗標可以找出位於其他工作中的現有 Activity,然後將它放置於可以回應意圖的地方。
</p>
<p class="note"><strong>注意:</strong>如果指定 Activity 的啟動模式為 {@code "standard"},它也會從堆疊中移除,改為啟動新的執行個體處理傳入的意圖。
這是因為當啟動模式為 {@code "standard"} 時,一律會為新的意圖建立新的執行個體。
</p>
</dd>
</dl>
<h3 id="Affinities">處理親和性</h3>
<p>親和性<em></em>可指出 Activity 偏好屬於哪個工作。根據預設,相同應用程式的所有 Activity 間互相都有親和性。
因此,根據預設,相同應用程式的所有 Activity 都偏好位於相同的工作。
不過,您可以修改 Activity 的預設親和性。
不同應用程式中定義的 Activity 可以共用親和性,或者相同應用程式中定義的 Activity 可以指派不同的工作親和性。
</p>
<p>您可以使用 <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a> 元素的 <a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">{@code taskAffinity}</a> 屬性修改任何指定 Activity 的親和性。
</p>
<p><a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">{@code taskAffinity}</a> 屬性使用字串值,但必須與 <a href="{@docRoot}guide/topics/manifest/manifest-element.html">
{@code &lt;manifest&gt;}</a> 元素中宣告的預設封裝名稱不同,因為系統使用該名稱來識別應用程式的預設工作親和性。
</p>
<p>在兩種情況下會用到親和性:</p>
<ul>
<li>當啟動 Activity 的意圖包含
{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} 旗標。
<p>根據預設,新的 Activity 會啟動至 Activity (名為 {@link android.app.Activity#startActivity startActivity()}) 的工作中。
系統會將它推入至與呼叫端相同的返回堆疊。
不過,如果傳送至
{@link android.app.Activity#startActivity startActivity()} 的意圖包含 {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} 旗標,則系統會找尋不同的工作來放置新的 Activity。
這通常是新工作。
不過,它不一定要是新工作。如果現有工作中有與新 Activity 相同的親和性,Activity 會啟動至該工作中。
如果沒有,會開始新的工作。</p>
<p>如果此旗標導致 Activity 開始新的工作,而使用者按 [首頁] 按鈕離開它,必須要有方法可以讓使用者回來瀏覽這個工作。<em></em>
有些實體 (例如,通知管理員) 總是從外部工作開始 Activity,從來不使用自己的工作,因此他們都會將 {@code FLAG_ACTIVITY_NEW_TASK} 放入傳送到
{@link android.app.Activity#startActivity startActivity()} 的意圖。
如果您的 Activity 可以由外部實體呼叫且可能使用此旗標,記得要提供使用者獨立的方法回到啟動的工作,例如,透過啟動組件圖示 (工作的根 Activity 有一個 {@link android.content.Intent#CATEGORY_LAUNCHER} 意圖篩選器;請參閱下方的<a href="#Starting">開始工作</a>)。
</p>
</li>
<li>當 Activity 的<a href="{@docRoot}guide/topics/manifest/activity-element.html#reparent">
{@code allowTaskReparenting}</a> 屬性設為 {@code "true"}。
<p>在這種情況下,當工作移到前景時,Activity 可以從其啟動的工作移到與其有親和性的工作。
</p>
<p>例如,假設將報告所選城市天氣狀況的 Activity 定義為旅遊應用程式的一部份。
它與相同應用程式中的其他 Activity 有相同的親和性 (預設的應用程式親和性),而且它允許與此屬性重設父代。
當您的其中一個 Activity 開始氣象報告程式 Activity,它一開始屬於與您 Activity 相同的工作。
不過,當旅遊應用程式工作移到前景,氣象報告程式 Activity 就會重新指派給該工作,並在其中顯示。
</p>
</li>
</ul>
<p class="note"><strong>提示:</strong>如果從使用者的角度來看 {@code .apk} 檔案包含一個以上的「應用程式」,您可能會想要使用 <a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">{@code taskAffinity}</a> 屬性對與每個「應用程式」關聯的 Activity 指派不同的親和性。
</p>
<h3 id="Clearing">清除返回堆疊</h3>
<p>如果使用者離開工作一段很長的時間,系統會清除根 Activity 以外所有 Activity 的工作
。當使用者再次回到工作,只會復原根 Activity。
系統會有這樣的行為是因為在一段很長的時間後,使用者很可能會放棄他們之前在做的工作,並回到工作開始其他新的工作。
</p>
<p>您可以使用下列一些 Activity 屬性來修改這個行為: </p>
<dl>
<dt><code><a
href="{@docRoot}guide/topics/manifest/activity-element.html#always">alwaysRetainTaskState</a></code>
</dt>
<dd>如果這項屬性在工作的根 Activity 中設為 {@code "true"},則剛描述的預設行為不會發生。
即使過了很長的一段時間,工作仍然會在堆疊保留所有的 Activity。
</dd>
<dt><code><a
href="{@docRoot}guide/topics/manifest/activity-element.html#clear">clearTaskOnLaunch</a></code></dt>
<dd>如果這項屬性在工作的根 Activity 中設為 {@code "true"},則剛描述的預設行為不會發生。
即使過了很長的一段時間,工作仍然會在堆疊保留所有的 Activity。
換句話說,它與
<a href="{@docRoot}guide/topics/manifest/activity-element.html#always">
{@code alwaysRetainTaskState}</a> 相反。即便使用者只離開工作一小段時間,使用者還是會回到工作的起始狀態。
</dd>
<dt><code><a
href="{@docRoot}guide/topics/manifest/activity-element.html#finish">finishOnTaskLaunch</a></code>
</dt>
<dd>這項屬性與 <a href="{@docRoot}guide/topics/manifest/activity-element.html#clear">{@code clearTaskOnLaunch}</a> 相似,但它在單一 Activity 上作業,而不是在整個工作。
它也會導致任何 Activity 離開,包含根 Activity。
如果設成 {@code "true"},Activity 只會在目前的工作階段留在此工作中。
如果使用者離開後再回到工作,該工作將不再存在。
</dd>
</dl>
<h3 id="Starting">開始工作</h3>
<p>您可以給予 Activity 一個意圖篩選器,將
{@code "android.intent.action.MAIN"} 設定為指定的動作,
{@code "android.intent.category.LAUNCHER"} 設定為指定的類別,以便將該 Activity 設定為工作的進入點。
例如:</p>
<pre>
&lt;activity ... &gt;
&lt;intent-filter ... &gt;
&lt;action android:name="android.intent.action.MAIN" /&gt;
&lt;category android:name="android.intent.category.LAUNCHER" /&gt;
&lt;/intent-filter&gt;
...
&lt;/activity&gt;
</pre>
<p>這類意圖篩選器可在應用程式啟動組件顯示 Activity 的圖示和標籤,讓使用者啟動 Activity 並回到 Activity 啟動後任何時間建立的工作。
</p>
<p>第二項功能很重要:使用者必須能夠在離開工作後,使用此 Activity 啟動組件回到此工作。
由於這個原因,兩個將 Activity 標示為一律啟動工作的<a href="#LaunchModes">啟動模式</a> {@code "singleTask"} 和
{@code "singleInstance"},應只能在 Activity 有 {@link android.content.Intent#ACTION_MAIN} 和 {@link android.content.Intent#CATEGORY_LAUNCHER} 篩選器時才能使用。
例如,試想如果缺少篩選器會發生什麼情況:
意圖會啟動 {@code "singleTask"} Activity、起始新工作,然後使用者會花一些時間在該工作進行作業。
之後,使用者按下 [首頁]<em></em> 按鈕。
此工作現在會傳送到背景而且不會顯示。現在,使用者沒有辦法回到工作,這是因為應用程式啟動組件沒有代表此工作的項目。
</p>
<p>在您不希望使用者返回 Activity 的情況下,將
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code> 元素的
<a href="{@docRoot}guide/topics/manifest/activity-element.html#finish">{@code finishOnTaskLaunch}</a> 設定為 {@code "true"} (請參閱<a href="#Clearing">清除堆疊</a>)。
</p>
<p>如要進一步瞭解工作和 Activity 在總覽畫面中的顯示及管理方式,請參閱<a href="{@docRoot}guide/components/recents.html">總覽畫面</a>。
</p>
<!--
<h2>Beginner's Path</h2>
<p>For more information about how to use intents to
activate other application components and publish the intents to which your components
respond, continue with the <b><a
href="{@docRoot}guide/components/intents-filters.html">Intents and Intent
Filters</a></b> document.</p>
-->