blob: 8bdb39410ce4e5a083d2ded339fdc8e9154e8bc5 [file] [log] [blame]
page.title=Задачи и стек переходов назад
parent.title=Операции
parent.link=activities.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Содержание документа</h2>
<ol>
<li><a href="#ActivityState">Сохранение состояния операции</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">операций</a>. Каждая операция
должна разрабатываться в связи с действием определенного типа, которое пользователь может выполнять, и может запускать другие
операции. Например, приложение электронной почты может содержать одну операцию для отображения списка новых сообщений.
Когда пользователь выбирает сообщение, открывается новая операция для просмотра этого сообщения.</p>
<p>Операция может даже запускать операции, существующие в других приложениях на устройстве. Например,
если ваше приложение хочет отправить сообщение электронной почты, вы можете определить намерение для выполнения
действия «отправить» и включить в него некоторые данные, например, адрес электронной почты и текст сообщения. После этого открывается операция из другого
приложения, которая объявила, что она обрабатывает намерения такого типа. В этом случае намерение состоит в том, чтобы
отправить сообщение электронной почты, поэтому в приложении электронной почты запускается операция «составить сообщение» (если одно намерение
может обрабатываться несколькими операциями, система предлагает пользователю выбрать, какую из операций использовать). После отправки сообщения электронной почты
ваша операция возобновляет работу, и все выглядит так, будто операция отправки электронной почты является частью вашего приложения. Хотя
операции могут быть частями разных приложений, система Android поддерживает удобство работы
пользователя, сохраняя обе операции в одной <em>задаче</em>.</p>
<p>Задача — это коллекция операций, с которыми взаимодействует пользователь
при выполнении определенного задания. Операции упорядочены в виде стека (<em>стека переходов назад</em>), в том
порядке, в котором открывались операции.</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>Начальным местом для большинства задач является главный экран устройства. Когда пользователь касается значка в средстве
запуска
приложений (или ярлыка на главном экране), эта задача приложения переходит на передний план. Если для
приложения нет задач (приложение не использовалось в последнее время), тогда создается новая задача
и открывается «основная» операция для этого приложения в качестве корневой операции в стеке.</p>
<p>Когда текущая операция запускает другую, новая операция помещается в вершину стека
и получает фокус. Предыдущая операция остается в стеке, но ее выполнение останавливается. Когда операция останавливается
, система сохраняет текущее состояние ее пользовательского интерфейса. Когда пользователь нажимает кнопку
<em>Назад</em>,
текущая операция удаляется из вершины стека (операция уничтожается) и возобновляется
работа предыдущей операции (восстанавливается предыдущее состояние ее пользовательского интерфейса). Операции в стеке
никогда не переупорядочиваются, только добавляются в стек и удаляются из него — добавляются в стек при запуске текущей операцией
и удаляются, когда пользователь выходит из нее с помощью кнопки <em>Назад</em>. По существу,
стек
переходов назад работает по принципу «последним вошел — первым вышел». На рисунке 1 это поведение
показано на временной шкале: состояние операций и текущее состояние стека переходов назад
показано в каждый момент времени.</p>
<img src="{@docRoot}images/fundamentals/diagram_backstack.png" alt="" />
<p class="img-caption"><strong>Рисунок 1.</strong> Иллюстрация того, как каждая новая операция в задаче
добавляет элемент в стек переходов назад. Когда пользователь нажимает кнопку<em>Назад</em>, текущая
операция
уничтожается, и возобновляется работа предыдущей операции.</p>
<p>Если пользователь продолжает нажимать кнопку <em>Назад</em>, операции поочередно удаляются из стека,
открывая
предыдущую операцию, пока пользователь не вернется на главный экран (или в операцию, которая была запущена
в начале выполнения задачи). Когда все операции удалены из стека, задача прекращает существование.</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> Создается несколько экземпляров одной операции.</p>
</div>
<p>Задача — это связанный блок, который может переходить в фоновый режим, когда пользователи начинают новую задачу или переходят
на главный экран с помощью кнопки <em>Домой</em>. В фоновом режиме все операции
задачи
остановлены, но стек обратного вызова для задачи остается неизменным. Задача просто потеряла фокус во время
выполнения другой задачи, как показано на рисунке 2. Затем задача может вернуться на передний план, так что пользователи
могут продолжить ее с прерванного места. Предположим, например, что текущая задача (Задача A) содержит три операции
в своем стеке — две операции под текущей операцией. Пользователь нажимает кнопку <em>Домой</em>,
затем запускает
новое приложение из средства запуска приложений. Когда появляется главный экран, Задача A переходит
в фоновый режим. Когда запускается новое приложение, система запускает задачу для этого приложения
(Задачу B) со своим собственным стеком операций. После взаимодействия с этим
приложением пользователь снова возвращается на главный экран и выбирает изначально запущенную
Задачу A. Теперь Задача A переходит на передний
план — все три операции ее стека остались неизменными, и возобновляется операция, находящаяся на
вершине стека. В этот
момент пользователь может также переключиться обратно на Задачу B, перейдя на главный экран и выбрав значок приложения,
которое запустило эту задачу (или выбрав задачу приложения на
<a href="{@docRoot}guide/components/recents.html">экране обзора</a>).
Это пример многозадачности в системе Android.</p>
<p class="note"><strong>Примечание.</strong> В фоновом режиме может находиться несколько задач одновременно.
Однако, если пользователь запускает много фоновых задач одновременно, система может начать
уничтожение фоновых операций для освобождения памяти, что приведет к потере состояния задач.
См. следующий раздел <a href="#ActivityState">Состояние операции</a>.</p>
<p>Поскольку операции в стеке никогда не переупорядочиваются, если ваше приложение позволяет
пользователям запускать определенную операцию из нескольких операций, новый экземпляр
такой операции создается и помещается в стек (вместо помещения любого из предыдущих экземпляров
операции на вершину стека). По существу, для одной операции вашего приложения может быть создано несколько
экземпляров (даже из разных задач), как показано на рисунке 3. Поэтому, если пользователь переходит назад с помощью
кнопки <em>Назад</em>, каждый экземпляр операции появляется в том порядке, в котором они
были открыты (каждый
со своим состоянием пользовательского интерфейса). Однако вы можете изменить это поведение, если вы не хотите, чтобы создавалось несколько
экземпляров операции. Это описано в разделе <a href="#ManagingTasks">Управление задачами</a> ниже.</p>
<p>Подведем итоги поведения операций и задач:</p>
<ul>
<li>Когда Операция A запускает Операцию B, Операция A останавливается, но система сохраняет ее состояние
(например, положение прокрутки и текст, введенный в формы).
Если пользователь нажимает кнопку <em>Назад</em> в Операции B, Операция A возобновляет работу
из сохраненного состояния.</li>
<li>Когда пользователь выходит из задачи нажатием кнопки <em>Домой</em>, текущая операция
останавливается и
ее задача переводится в фоновый режим. Система сохраняет состояние каждой операции в задаче. Если
пользователь впоследствии возобновляет задачу, выбирая значок запуска задачи, она переводится
на передний план и возобновляет операцию на вершине стека.</li>
<li>Если пользователь нажимает кнопку <em>Назад</em>, текущая операция удаляется из стека
и
уничтожается. Возобновляется предыдущая операция в стеке. Когда операция уничтожается, система
<em>не</em> сохраняет состояние операции.</li>
<li>Можно создавать несколько экземпляров операции, даже из других задач.</li>
</ul>
<div class="note design">
<p><strong>Дизайн навигации</strong></p>
<p>Для получения дополнительной информации о работе навигации в приложении Android, прочитайте раздел <a href="{@docRoot}design/patterns/navigation.html">Навигация</a> руководства «Дизайн для Android».</p>
</div>
<h2 id="ActivityState">Сохранение состояния операции</h2>
<p>Как говорилось выше, система по умолчанию сохраняет состояние операции, когда она
останавливается. Таким образом, когда пользователи возвращаются обратно в предыдущую операцию, восстанавливается ее пользовательский интерфейс
в момент остановки. Однако вы можете — и <strong>должны</strong> — с упреждением сохранять
состояние ваших операций посредством методов обратного вызова на случай уничтожения операции и необходимости ее
повторного создания.</p>
<p>Когда система останавливает одну из ваших операций (например, когда запускается новая операция или задача
перемещается в фоновый режим), система может полностью уничтожить эту операцию, если необходимо восстановить
память системы. Когда это происходит, информация о состоянии операции теряется. Если это происходит,
система
знает, что операция находится в стеке переходов назад, но когда операция переходит
на вершину стека, система должна создать ее повторно (а не возобновить ее). Чтобы избежать
потери работы пользователя, вы должны с упреждением сохранять ее путем реализации методов
обратного вызова {@link android.app.Activity#onSaveInstanceState onSaveInstanceState()}
в вашей операции.</p>
<p>Дополнительную информацию о сохранении состояния вашей операции см. в документе
<a href="{@docRoot}guide/components/activities.html#SavingActivityState">Операции</a>.</p>
<h2 id="ManagingTasks">Управление задачами</h2>
<p>Для большинства приложений способ, которым Android управляет задачами и стеком переходов назад, описанный выше, — помещение всех
операций последовательно в одну задачу в стек «последним вошёл — первым вышел», —
работает хорошо, и вы не должны беспокоиться о связи ваших операций с задачами
или об их существовании в стеке переходов назад. Однако вы можете решить, что вы хотите прервать
обычное поведение. Возможно, вы хотите, чтобы операция в вашем приложении начинала новую задачу
при запуске (вместо помещения в текущую задачу), или при запуске операции вы хотите
перенести на передний план ее существующий экземпляр (вместо создания нового
экземпляра на вершине стека переходов назад), или вы хотите чтобы при выходе пользователя из задачи из вашего стек переходов удалялись все
операции, кроме корневой операции.</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>В следующих разделах показано, как можно использовать эти атрибуты манифеста и флаги
намерений для определения связи операций с задачами и их поведения в стеке переходов назад.</p>
<p>Кроме того, отдельно обсуждаются рекомендации о представлении задач и операций и управлении ими
на экране обзора. Дополнительную информацию см. в разделе
<a href="{@docRoot}guide/components/recents.html">Экран обзора</a>. Обычно следует разрешить системе определить способ представления вашей задачи и
операций на экране обзора. Вам не нужно менять это поведение.</p>
<p class="caution"><strong>Внимание!</strong> В большинстве приложений не следует прерывать поведение
операций и задач по умолчанию. Если вы обнаружили, что вашей операции необходимо изменить
поведение по умолчанию, будьте внимательны и протестируйте удобство работы с операцией во время
запуска и при обратной навигации к ней из других операций и задач с помощью кнопки <em>Назад</em>.
Обязательно протестируйте поведение навигации, которое может противоречить поведению, ожидаемому пользователем.</p>
<h3 id="TaskLaunchModes">Определение режимов запуска</h3>
<p>Режимы запуска позволяют вам определять связь нового экземпляра операции
с текущей задачей. Вы можете задавать различные режимы запуска двумя способами:</p>
<ul class="nolist">
<li><a href="#ManifestForTasks">Использование файла манифеста</a>
<p>Когда вы объявляете операцию в вашем файле манифеста, вы можете указать, как операция
должна связываться с задачами при ее запуске.</li>
<li><a href="#IntentFlagsForTasks">Использование флагов намерений</a>
<p>Когда вы вызываете {@link android.app.Activity#startActivity startActivity()},
вы можете включить флаг в {@link android.content.Intent}, который объявляет, как должна быть связана
новая операция с текущей задачей (и должна ли).</p></li>
</ul>
<p>По существу, если Операция A запускает Операцию B, Операция B может определить в своем манифесте, как она
должна быть связана с текущей задачей (если вообще должна), а Операция A может также запросить, как Операция B
должна быть связана с текущей задачей. Если обе операции определяют, как Операция B
должна быть связана с задачей, тогда запрос Операции A (как определено в намерении) обрабатывается через
запрос Операции B (как определено в ее манифесте).</p>
<p class="note"><strong>Примечание.</strong> Некоторые режимы запуска, доступные для файла манифеста,
недоступны в виде флагов для намерения и, аналогичным образом, некоторые режимы запуска, доступные в виде флагов
для намерения, не могут быть определены в манифесте.</p>
<h4 id="ManifestForTasks">Использование файла манифеста</h4>
<p>При объявлении операции в вашем файле манифеста вы можете указать, как операция должна
быть связана с задачей посредством атрибута <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code
launchMode}</a>
элемента <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a>.</p>
<p>Атрибут <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code
launchMode}</a> указывает инструкцию по запуску операции в
задаче. Существует четыре различных режима запуска,
которые вы можете назначить атрибуту
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">launchMode</a></code>:</p>
<dl>
<dt>{@code "standard"} (режим по умолчанию)</dt>
<dd>Режим по умолчанию. Система создает новый экземпляр операции в задаче, из
которой она была запущена, и направляет ему намерение. Может быть создано несколько экземпляров операции,
каждый экземпляр может принадлежать различным задачам, и одна задача может содержать несколько экземпляров.</dd>
<dt>{@code "singleTop"}</dt>
<dd>Если экземпляр операции уже существует на вершине текущей задачи, система
направляет намерение в этот экземпляр путем вызова его метода {@link
android.app.Activity#onNewIntent onNewIntent()}, а не путем создания нового экземпляра
операции. Может быть создано несколько экземпляров операции, каждый экземпляр может
принадлежать различным задачам, и одна задача может содержать несколько экземпляров (но только если
операция на вершине стека переходов назад <em>не</em> является существующим экземпляром операции).
<p>Предположим, что стек переходов назад задачи состоит из корневой операции A с операциями B, C
и D на вершине (стек имеет вид A-B-C-D и D находится на вершине). Поступает намерение для операции типа D.
Если D имеет режим запуска {@code "standard"} по умолчанию, запускается новый экземпляр класса и
стек принимает вид A-B-C-D-D. Однако, если D имеет режим запуска {@code "singleTop"}, существующий экземпляр
D получает намерение через {@link
android.app.Activity#onNewIntent onNewIntent()}, так как этот экземпляр находится на вершине стека —
стек сохраняет вид A-B-C-D. Однако, если поступает намерение для операции типа B, тогда в стек
добавляется новый экземпляр B, даже если он имеет режим запуска {@code "singleTop"}.</p>
<p class="note"><strong>Примечание.</strong> Когда создается новый экземпляр операции,
пользователь может нажать кнопку <em>Назад</em> для возврата к предыдущей операции. Но когда существующий
экземпляр
операции обрабатывает новое намерение, пользователь не может нажать кнопку <em>Назад</em> для возврата к
состоянию
операции до поступления нового намерения в {@link android.app.Activity#onNewIntent
onNewIntent()}.</p>
</dd>
<dt>{@code "singleTask"}</dt>
<dd>Система создает новую задачу и создает экземпляр операции в корне новой задачи.
Однако, если экземпляр операции уже существует в отдельной задаче, система направляет
намерение в существующий экземпляр путем вызова его метода {@link
android.app.Activity#onNewIntent onNewIntent()}, а не путем создания нового экземпляра. Одновременно
может существовать только один экземпляр операции.
<p class="note"><strong>Примечание.</strong> Хотя операция запускает новую задачу, кнопка
<em>Назад</em> возвращает пользователя к предыдущей операции.</p></dd>
<dt>{@code "singleInstance"}.</dt>
<dd>То же, что и {@code "singleTask"}, но при этом система не запускает никаких других операций
в задаче, содержащей этот экземпляр. Операция всегда является единственным членом своей задачи;
любые операции, запущенные этой операцией, открываются в отдельной задаче.</dd>
</dl>
<p>В качестве другого примера: приложение Android Browser объявляет, что операция веб-браузера должна
всегда открываться в своей собственной задаче — путем указания режима запуска {@code singleTask} в элементе <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a>.
Это означает, что если ваше приложение выдает
намерение открыть Android Browser, его операция <em>не</em> помещается в ту же
задачу, что и ваше приложение. Вместо этого, либо для браузера запускается новая задача, либо, если браузер уже
имеет задачу, работающую в фоновом режиме, эта задача переводится на передний план для обработки нового
намерения.</p>
<p>И при запуске операции в новой задаче, и при запуске операции в существующей задаче,
кнопка <em>Назад</em> всегда возвращает пользователя к предыдущей операции. Однако, если вы
запускаете операцию, которая указывает режим запуска {@code singleTask}, вся задача переводится на передний план, если экземпляр
этой операции существует в фоновой задаче. В этот момент
стек переходов назад помещает все операции из задачи, переведенной на передний план, на вершину
стека. Рисунок 4 иллюстрирует сценарий этого типа.</p>
<img src="{@docRoot}images/fundamentals/diagram_backstack_singletask_multiactivity.png" alt="" />
<p class="img-caption"><strong>Рисунок 4.</strong> Представление того, как операция с режимом
запуска singleTask добавляется в стек переходов назад. Если операция уже является частью
фоновой задачи со своим собственным стеком переходов назад, то весь стек переходов назад также переносится вверх,
на вершину текущей задачи.</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>,
может быть переопределено флагами, включенными в намерение, которое запускает вашу операцию, как описано
в следующем разделе.</p>
<h4 id="#IntentFlagsForTasks">Использование флагов намерений</h4>
<p>При запуске операции вы можете изменить связывание операции с ее задачей по умолчанию
путем включения флагов в намерение, которое доставляется в {@link
android.app.Activity#startActivity startActivity()}. Для изменения поведения по умолчанию
вы можете использовать следующие флаги:</p>
<p>
<dt>{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}</dt>
<dd>Запуск операции в новой задаче. Если задача уже работает для операции, которую вы запускаете
сейчас, эта задача переводится на передний план, ее последнее состояние восстанавливается, и операция получает
новое намерение в {@link android.app.Activity#onNewIntent onNewIntent()}.
<p>Это приводит к тому же поведению, что и значение <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a> в режиме {@code "singleTask"},
как описано в предыдущем разделе.</p></dd>
<dt>{@link android.content.Intent#FLAG_ACTIVITY_SINGLE_TOP}</dt>
<dd>Если запускаемая операция является текущей операцией (находится на вершине стека переходов назад), тогда
вызов в {@link android.app.Activity#onNewIntent onNewIntent()} получает существующий экземпляр,
без создания нового экземпляра операции.
<p>Это приводит к тому же поведению, что и значение <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a> в режиме {@code "singleTop"},
как описано в предыдущем разделе.</p></dd>
<dt>{@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP}</dt>
<dd>Если запускаемая операция уже работает в текущей задаче, тогда вместо
запуска нового экземпляра этой операции уничтожаются все другие операции, расположенные в стеке выше нее
, и это намерение доставляется в возобновленный экземпляр этой операции (которая теперь находится на вершине стека)
посредством {@link android.app.Activity#onNewIntent onNewIntent()}).
<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}.
При использовании вместе эти флаги позволяют найти существующую операцию
в другой задаче и поместить ее в положение, где она сможет реагировать на намерение. </p>
<p class="note"><strong>Примечание.</strong> Если для назначенной операции установлен режим запуска
{@code "standard"},
она также удаляется из стека и на ее месте запускается новый экземпляр, чтобы обработать
входящее намерение. Именно поэтому в режиме запуска {@code "standard"} всегда создается новый
экземпляр для нового намерения. </p>
</dd>
</dl>
<h3 id="Affinities">Обработка привязок</h3>
<p><em>Привязка</em> указывает предпочтительную принадлежность операции к задаче. По умолчанию все
операции из одного приложения имеют привязку друг к другу. Поэтому по умолчанию все
операции одного приложения предпочитают находиться в одной задаче. Однако вы можете изменить
привязку по умолчанию для операции. Операции, определенные
в разных приложениях, могут совместно использовать одну привязку; таким же образом операции, определенные в одном приложении, могут получить
привязки к разным задачам.</p>
<p>Вы можете изменить привязку любой данный операции с помощью
атрибута <a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">{@code taskAffinity}</a>
элемента <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a>.</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>Когда намерение, запускающее
операцию, содержит флаг
{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}.
<p>Новая операция по умолчанию запускается в задаче той операции,
которая вызвала {@link android.app.Activity#startActivity startActivity()}. Она помещается в тот же
стек переходов назад, что и вызывающая операция. Однако, если намерение, переданное
в {@link android.app.Activity#startActivity startActivity()},
содержит флаг {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK},
система ищет другую задачу для помещения новой операции. Часто это новая задача.
Но необязательно. Если уже существует задача с той же привязкой, что
и у новой операции, операция запускается в этой задаче. Если нет, операция начинает новую задачу.</p>
<p>Если этот флаг приводит к тому, что операция начинает новую задачу, и пользователь нажимает кнопку <em>Домой</em>
для выхода из нее,
должен существовать способ, позволяющий пользователю вернуться к задаче. Некоторые объекты (такие как
диспетчер уведомлений) всегда запускают операции во внешней задаче, а не в составе собственной, поэтому
они всегда помещают флаг {@code FLAG_ACTIVITY_NEW_TASK} в намерения, которые они передают
в {@link android.app.Activity#startActivity startActivity()}.
Если у вас есть операция, которую можно вызвать
внешним объектом, использующим этот флаг, позаботьтесь о том, чтобы у пользователя был независимый способ
вернуться в запущенную задачу, например, с помощью значка запуска (корневая операция задачи
содержит фильтр намерений {@link android.content.Intent#CATEGORY_LAUNCHER}; см. раздел <a href="#Starting">Запуск задачи</a> ниже).</p>
</li>
<li>Если для атрибута <a href="{@docRoot}guide/topics/manifest/activity-element.html#reparent">
{@code allowTaskReparenting}</a> операции установлено значение {@code "true"}.
<p>В этом случае операция может переместиться из запустившей ее задачи в задачу, к которой у операции есть привязка,
когда эта задача переходит на передний план.</p>
<p>Предположим, что операция, которая сообщает о погодных условиях в выбранных городах,
определена в составе приложения для путешественников. Она имеет ту же привязку, что и другие операции в том же
приложении (привязка приложения по умолчанию), и допускает переподчинение с этим атрибутом.
Когда одна из ваших операций запускает операцию прогноза погоды, она изначально принадлежит той же
задаче, что и ваша операция. Однако, когда задача из приложения для путешественников переходит на передний план,
операция прогноза погоды переназначается этой задаче и отображается внутри нее.</p>
</li>
</ul>
<p class="note"><strong>Совет.</strong> Если файл {@code .apk} содержит более одного «приложения»
с точки зрения пользователя, вы, вероятно, захотите использовать атрибут <a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">{@code taskAffinity}</a>
для назначения разных привязок операциям, связанным с каждым «приложением».</p>
<h3 id="Clearing">Очистка стека переходов назад</h3>
<p>Если пользователь выходит из задачи на длительное время, система удаляет из задачи все операции, кроме
корневой операции. Когда пользователь возвращается в задачу, восстанавливается только корневая операция.
Система ведет себя таким образом, так как после продолжительного времени пользователи обычно уже забросили то,
чем они занимались ранее, и возвращаются в задачу, чтобы начать что-то новое. </p>
<p>Для изменения такого поведения предусмотрено несколько атрибутов операции, которыми вы можете воспользоваться: </p>
<dl>
<dt><code><a
href="{@docRoot}guide/topics/manifest/activity-element.html#always">alwaysRetainTaskState</a></code>
</dt>
<dd>Если для этого атрибута установлено значение {@code "true"} в корневой операции задачи,
описанное выше поведение по умолчанию не происходит.
Задача восстанавливает все операции в своем стеке даже по истечении длительного периода времени.</dd>
<dt><code><a
href="{@docRoot}guide/topics/manifest/activity-element.html#clear">clearTaskOnLaunch</a></code></dt>
<dd>Если для этого атрибута установлено значение {@code "true"} в корневой операции задачи,
стек очищается до корневой операции каждый раз, когда пользователь выходит из задачи
и возвращается в нее. Другими словами, этот атрибут противоположен атрибуту
<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>,
но он действует на
одну операцию, а не на всю задачу. Он также может приводить к удалению любой операции,
включая корневую операцию. Когда для него установлено значение {@code "true"},
операция остается частью задачи только для текущего сеанса. Если пользователь
выходит из задачи, а затем возвращается в нее, операция уже отсутствует.</dd>
</dl>
<h3 id="Starting">Запуск задачи</h3>
<p>Вы можете сделать операцию точкой входа, назначая ей фильтр намерений со значением
{@code "android.intent.action.MAIN"} в качестве указанного действия и
{@code "android.intent.category.LAUNCHER"}
в качестве указанной категории. Например:</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>Фильтр намерений такого типа приводит к тому, что в средстве запуска приложения отображаются значок и метка для
операции, что позволяет пользователю запускать операцию
и возвращаться в создавшую ее задачу в любой момент после ее запуска.
</p>
<p>Эта вторая возможность очень важна: пользователи должны иметь возможность выходить из задачи и затем возвращаться в нее
с помощью этого средства запуска операции. Поэтому два <a href="#LaunchModes">режима
запуска</a>, которые отмечают, что операции всегда инициируют задачу, {@code "singleTask"} и
{@code "singleInstance"}, должны использоваться только в тех случаях, когда операция содержит
{@link android.content.Intent#ACTION_MAIN}
и фильтр {@link android.content.Intent#CATEGORY_LAUNCHER}. Представьте, например, что может произойти,
если фильтр отсутствует: намерение запускает операцию {@code "singleTask"}, которая инициирует
новую задачу, и пользователь некоторое время работает в этой задаче. Затем пользователь нажимает кнопку
<em>Домой</em>. Задача переводится в фоновый режим и не отображается. Теперь у пользователя нет возможности вернуться
к задаче, так как она отсутствует в средстве запуска приложения.</p>
<p>Для таких случаев, когда вы не хотите, чтобы пользователь мог вернуться к операции, установите для атрибута
<a href="{@docRoot}guide/topics/manifest/activity-element.html#finish">{@code finishOnTaskLaunch}</a>
элемента
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
значение {@code "true"} (см. раздел <a href="#Clearing">Очистка стека</a>).</p>
<p>Дополнительную информацию о представлении задач и операций и управлении ими
на экране обзора см. в разделе <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>
-->