| page.title=Операции |
| page.tags=операция,намерение |
| @jd:body |
| |
| <div id="qv-wrapper"> |
| <div id="qv"> |
| <h2>Содержание документа</h2> |
| <ol> |
| <li><a href="#Creating">Создание операции</a> |
| <ol> |
| <li><a href="#UI">Реализация пользовательского интерфейса</a></li> |
| <li><a href="#Declaring">Объявление операции в манифесте</a></li> |
| </ol> |
| </li> |
| <li><a href="#StartingAnActivity">Запуск операции</a> |
| <ol> |
| <li><a href="#StartingAnActivityForResult">Запуск операции для получения результата</a></li> |
| </ol> |
| </li> |
| <li><a href="#ShuttingDown">Завершение операции</a></li> |
| <li><a href="#Lifecycle">Управление жизненным циклом операций</a> |
| <ol> |
| <li><a href="#ImplementingLifecycleCallbacks">Реализация обратных вызовов жизненного цикла</a></li> |
| <li><a href="#SavingActivityState">Сохранение состояния операции</a></li> |
| <li><a href="#ConfigurationChanges">Обработка изменений в конфигурации</a></li> |
| <li><a href="#CoordinatingActivities">Согласование операций</a></li> |
| </ol> |
| </li> |
| </ol> |
| |
| <h2>Ключевые классы</h2> |
| <ol> |
| <li>{@link android.app.Activity}</li> |
| </ol> |
| |
| <h2>См. также:</h2> |
| <ol> |
| <li><a href="{@docRoot}guide/components/tasks-and-back-stack.html">Задачи и стек |
| переходов назад</a></li> |
| </ol> |
| |
| </div> |
| </div> |
| |
| |
| |
| <p>{@link android.app.Activity} — это компонент приложения, который выдает экран, |
| и с которым пользователи могут взаимодействовать для выполнения каких-либо действий, например набрать номер телефона, сделать фото, отправить письмо или |
| просмотреть карту. Каждой операции присваивается окно для прорисовки соответствующего пользовательского интерфейса. Обычно окно |
| отображается во весь экран, однако его размер может быть меньше, и оно может размещаться поверх других |
| окон.</p> |
| |
| <p> Как правило, приложение состоит из нескольких операций, которые слабо |
| связаны друг с другом. Обычно одна из операций в приложении обозначается как «основная», |
| предлагаемая пользователю при первом запуске приложения. В свою очередь, каждая |
| операция может запустить другую операцию для выполнения различных действий. Каждый раз, когда |
| запускается новая операция, предыдущая операция останавливается, однако система сохраняет ее |
| в стеке («стек переходов назад»). При запуске новой операции она помещается в стек переходов назад и |
| отображается для пользователя. Стек переходов назад работает по принципу «последним вошёл — первым вышел», |
| поэтому после того как пользователь завершил текущую операцию и нажал кнопку <em>Назад</em>, текущая операция |
| удаляется из стека (и уничтожается), и возобновляется предыдущая операция. (Подробные сведения о стеке |
| переходов назад представлены в статье <a href="{@docRoot}guide/components/tasks-and-back-stack.html">Задачи и стек |
| переходов назад</a>.)</p> |
| |
| <p>Когда операция останавливается по причине запуска новой операции, для уведомления об изменении ее состояния |
| используются методы обратного вызова жизненного цикла операции. |
| Существует несколько таких методов, которые может принимать операция вследствие изменения своего состояния |
| — создание операции, ее остановка, возобновление или уничтожение системой; также |
| каждый обратный вызов представляет возможность выполнить определенное действие, |
| подходящее для соответствующего изменения состояния. Например, в случае остановки операция должна освободить любые |
| крупные объекты, например, подключение к сети или базе данных. При возобновлении операции вы можете |
| повторно получить необходимые ресурсы и возобновить выполнение прерванных действий. Такие изменения состояния |
| являются частью жизненного цикла операции.</p> |
| |
| <p>Далее в этом документе рассматриваются основы создания и использования операций, |
| включая полное описание жизненного цикла операции, чтобы вы могли лучше понять, как следует управлять |
| переходами между различными состояниями операции.</p> |
| |
| |
| |
| <h2 id="Creating">Создание операции</h2> |
| |
| <p>Чтобы создать операцию, сначала необходимо создать подкласс класса {@link android.app.Activity} (или |
| воспользоваться существующим его подклассом). В таком подклассе необходимо реализовать методы обратного вызова, которые |
| вызывает система при переходе операции из одного состояния своего жизненного цикла в другое, например при |
| создании, остановке, возобновлении или уничтожении операции. Вот два наиболее важных метода |
| обратного вызова:</p> |
| |
| <dl> |
| <dt>{@link android.app.Activity#onCreate onCreate()}</dt> |
| <dd>Этот метод необходимо обязательно реализовать, поскольку система вызывает его при создании вашей |
| операции. В своей реализации вам необходимо инициализировать ключевые компоненты |
| операции. |
| Наиболее важно именно здесь вызвать {@link android.app.Activity#setContentView |
| setContentView()} для определения макета пользовательского интерфейса операции.</dd> |
| <dt>{@link android.app.Activity#onPause onPause()}</dt> |
| <dd>Система вызывает этот метод в качестве первого признака выхода пользователя из |
| операции (однако это не всегда означает, что операция будет уничтожена). Обычно именно здесь |
| необходимо применять любые изменения, которые должны быть сохранены помимо текущего сеанса работы пользователя (поскольку |
| пользователь может не вернуться назад).</dd> |
| </dl> |
| |
| <p>Существуют также и некоторые другие методы обратного вызова жизненного цикла, которые необходимо использовать для того, чтобы обеспечить |
| плавный переход между операциями, а также для обработки непредвиденных нарушений в работе операции, в результате которых она может быть |
| остановлена или даже уничтожена. Более подробное описание всех методов обратного вызова жизненного цикла представлены в разделе, |
| посвященном <a href="#Lifecycle">управлению жизненным циклом операций</a>.</p> |
| |
| |
| |
| <h3 id="UI">Реализация пользовательского интерфейса</h3> |
| |
| <p> Для реализации пользовательского интерфейса операции используется иерархия представлений —объектов, полученных из |
| класса {@link android.view.View}. Каждое представление отвечает за определенную прямоугольную область |
| окна операции и может реагировать на действия пользователей. Например, представлением может быть |
| кнопка, нажатие на которую приводит к выполнению определенного действия.</p> |
| |
| <p>В Android предусмотрен набор уже готовых представлений, которые можно использовать для создания дизайна макета и его |
| организации. Виджеты — это представления с визуальными (и интерактивными) элементами, например, |
| кнопками, текстовыми полями, чекбоксами или просто изображениями. Макеты — это представления, полученные из класса {@link |
| android.view.ViewGroup}, обеспечивающие уникальную модель компоновки для своих дочерних представлений, таких как линейный |
| макет, сетка или относительный макет. Также можно создать подкласс для классов {@link android.view.View} и |
| {@link android.view.ViewGroup} (или воспользоваться существующими подклассами), чтобы создать собственные виджеты и |
| макеты, и затем применить их к макету своей операции.</p> |
| |
| <p>Чаще всего для задания макета с помощью представлений используется XML-файл макета, сохраненный в |
| ресурсах приложения. Таким образом вы можете хранить дизайн пользовательского интерфейса отдельно от |
| исходного кода, который служит для задания поведения операции. Чтобы задать макет в качестве пользовательского интерфейса |
| операции, можно использовать метод {@link android.app.Activity#setContentView(int) setContentView()}, передав в него |
| идентификатор ресурса для макета. Однако вы также можете создать новые {@link android.view.View} в коде вашей |
| операции и создать иерархию представлений. Для этого вставьте {@link |
| android.view.View} в {@link android.view.ViewGroup}, а затем используйте этот макет, передав корневой объект |
| {@link android.view.ViewGroup} в метод {@link android.app.Activity#setContentView(View) |
| setContentView()}.</p> |
| |
| <p>Подробные сведения о создании пользовательского интерфейса см. в статье <a href="{@docRoot}guide/topics/ui/index.html">Пользовательский интерфейс</a>.</p> |
| |
| |
| |
| <h3 id="Declaring">Объявление операции в манифесте</h3> |
| |
| <p>Чтобы операция стала доступна системе, ее необходимо объявить в файле |
| манифеста. Для этого откройте файл манифеста и добавьте элемент <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> в |
| качестве дочернего для элемента |
| <a href="{@docRoot}guide/topics/manifest/application-element.html">{@code <application>}</a>. Например:</p> |
| |
| <pre> |
| <manifest ... > |
| <application ... > |
| <activity android:name=".ExampleActivity" /> |
| ... |
| </application ... > |
| ... |
| </manifest > |
| </pre> |
| |
| <p>Существует несколько других атрибутов, которые можно включить в этот элемент, чтобы определить такие |
| свойства, как метка операции, значок операции или тема оформления для пользовательского интерфейса операции. |
| Единственным обязательным атрибутом является <a href="{@docRoot}guide/topics/manifest/activity-element.html#nm">{@code android:name}</a> |
| — он определяет имя класса операции. После |
| публикации вашего приложения вам не следует переименовывать его, поскольку это может нарушить некоторые |
| функциональные возможности приложения, например, ярлыки приложения (ознакомьтесь с публикацией <a href="http://android-developers.blogspot.com/2011/06/things-that-cannot-change.html">Вещи |
| , которые нельзя менять</a> в блоге разработчиков).</p> |
| |
| <p>Дополнительные сведения об объявлении операции |
| в манифесте см. в справке по элементу <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a>.</p> |
| |
| |
| <h4>Использование фильтров намерений</h4> |
| |
| <p>Элемент <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code |
| <activity>}</a> также может задавать различные фильтры намерений — с помощью элемента <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code |
| <intent-filter>}</a> — для объявления того, как другие компоненты приложения |
| могут активировать операцию.</p> |
| |
| <p>При создании нового приложения с помощью инструментов Android SDK в заготовке операции, |
| создаваемой автоматически, имеется фильтр намерений, который объявляет операцию. |
| Эта операция реагирует на выполнение «основного» действия, и ее следует поместить в категорию переходсредства запуска. Фильтр намерений |
| выглядит следующим образом.</p> |
| |
| <pre> |
| <activity android:name=".ExampleActivity" android:icon="@drawable/app_icon"> |
| <intent-filter> |
| <action android:name="android.intent.action.MAIN" /> |
| <category android:name="android.intent.category.LAUNCHER" /> |
| </intent-filter> |
| </activity> |
| </pre> |
| |
| <p>Элемент <a href="{@docRoot}guide/topics/manifest/action-element.html">{@code |
| <action>}</a> указывает, что это «основная» точка входа в приложение. Элемент <a href="{@docRoot}guide/topics/manifest/category-element.html">{@code |
| <category>}</a>указывает, что эту операцию следует указать в |
| средстве запуска приложений системы (чтобы пользователи могли запускать эту операцию).</p> |
| |
| <p>Если приложение планируется создать самодостаточным и запретить другим приложениям активировать |
| его операции, то других фильтров намерений создавать не нужно. В этом случае только в одной операции |
| должно иметься «основное» действие, и ее следует поместить в категорию средства запуска, как в примере выше. В операциях, |
| которые не должны быть доступны для других приложений, не следует включать фильтры намерений. |
| Вы можете самостоятельно запустить такие операции с помощью явных намерений (как описывается в следующем разделе).</p> |
| |
| <p>Однако, если вам необходимо, чтобы операция реагировала на неявные намерения, |
| получаемые от других приложений (а также из вашего приложения), для операции необходимо определить дополнительные фильтры |
| намерений. Для каждого типа намерения, на который необходимо реагировать, необходимо указать объект <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code |
| <intent-filter>}</a>, включающий элемент |
| <a href="{@docRoot}guide/topics/manifest/action-element.html">{@code |
| <action>}</a> и необязательный элемент <a href="{@docRoot}guide/topics/manifest/category-element.html">{@code |
| <category>}</a> или <a href="{@docRoot}guide/topics/manifest/data-element.html">{@code |
| <data>}</a> (или оба этих элемента). Эти элементы определяют тип намерения, на который может реагировать |
| ваша операция.</p> |
| |
| <p>Дополнительные сведения о том, как операции могут реагировать на намерения, приведены в статье <a href="{@docRoot}guide/components/intents-filters.html">Намерения и фильтры намерений</a>. |
| </p> |
| |
| |
| |
| <h2 id="StartingAnActivity">Запуск операции</h2> |
| |
| <p>Для запуска другой операции достаточно вызвать метод {@link android.app.Activity#startActivity |
| startActivity()}, передав в него объект {@link android.content.Intent}, который описывает запускаемую |
| операцию. В намерении указывается либо точная операция для запуска, либо описывается |
| тип операции, которую вы хотите выполнить (после чего система выбирает для вас подходящую |
| операцию, которая |
| может даже находиться в другом приложении). Намерение также может содержать небольшой объем данных, |
| которые будут использоваться запущенной операцией.</p> |
| |
| <p>При работе с собственным приложением зачастую требуется лишь запустить нужную операцию. |
| Для этого необходимо создать намерение, которое явно определяет требуемую операцию |
| с помощью имени класса. Ниже представлен пример запуска одной операцией другой операции с именем {@code |
| SignInActivity}.</p> |
| |
| <pre> |
| Intent intent = new Intent(this, SignInActivity.class); |
| startActivity(intent); |
| </pre> |
| |
| <p>Однако в вашем приложении также может потребоваться выполнить некоторое действие, например, отправить письмо, текстовое |
| сообщение или обновить статус, используя данные из вашей операции. В этом случае в вашем приложении могут |
| отсутствовать такие действия, поэтому вы можете воспользоваться операциями |
| из других приложений, имеющихся на устройстве, которые могут выполнять требуемые действия. Как раз в этом случае |
| намерения особенно полезны — можно создать намерение, которое описывает необходимое действие, |
| после чего система |
| запускает его из другого приложения. При наличии |
| нескольких операций, которые могут обработать намерение, пользователь может выбирать, какое из них следует использовать. Например, |
| если пользователю требуется предоставить возможность отправить электронное письмо, можно создать |
| следующее намерение:</p> |
| |
| <pre> |
| Intent intent = new Intent(Intent.ACTION_SEND); |
| intent.putExtra(Intent.EXTRA_EMAIL, recipientArray); |
| startActivity(intent); |
| </pre> |
| |
| <p>Дополнительный компонент {@link android.content.Intent#EXTRA_EMAIL}, добавленный в намерение, представляет собой строковый массив |
| адресов электронной почты для отправки письма. Когда почтовая программа реагирует на это |
| намерение, она считывает дополнительно добавленный строковый массив и помещает имеющиеся в нем адреса в поле получателя |
| в окне создания письма. При этом запускается операция почтовой программы, а после того, как |
| пользователь завершит требуемые действия, возобновляется ваша операция.</p> |
| |
| |
| |
| |
| <h3 id="StartingAnActivityForResult">Запуск операции для получения результата</h3> |
| |
| <p>В некоторых случаях после запуска операции может потребоваться получить результат. Для этого |
| вызовите метод {@link android.app.Activity#startActivityForResult |
| startActivityForResult()} (вместо {@link android.app.Activity#startActivity |
| startActivity()}). Чтобы получить результат после выполнения последующей |
| операции, реализуйте метод обратного |
| вызова {@link android.app.Activity#onActivityResult onActivityResult()}. По завершении последующей операции она возвращает результат в объекте {@link |
| android.content.Intent} |
| в вызванный метод {@link android.app.Activity#onActivityResult onActivityResult()}.</p> |
| |
| <p>К примеру, пользователю потребуется выбрать один из контактов, чтобы ваша операция могла |
| выполнить некоторые действия с информацией об этом контакте. Ниже представлен пример создания такого намерения |
| и обработки результата.</p> |
| |
| <pre> |
| private void pickContact() { |
| // Create an intent to "pick" a contact, as defined by the content provider URI |
| Intent intent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI); |
| startActivityForResult(intent, PICK_CONTACT_REQUEST); |
| } |
| |
| @Override |
| protected void onActivityResult(int requestCode, int resultCode, Intent data) { |
| // If the request went well (OK) and the request was PICK_CONTACT_REQUEST |
| if (resultCode == Activity.RESULT_OK && requestCode == PICK_CONTACT_REQUEST) { |
| // Perform a query to the contact's content provider for the contact's name |
| Cursor cursor = getContentResolver().query(data.getData(), |
| new String[] {Contacts.DISPLAY_NAME}, null, null, null); |
| if (cursor.moveToFirst()) { // True if the cursor is not empty |
| int columnIndex = cursor.getColumnIndex(Contacts.DISPLAY_NAME); |
| String name = cursor.getString(columnIndex); |
| // Do something with the selected contact's name... |
| } |
| } |
| } |
| </pre> |
| |
| <p>В этом примере демонстрируется базовая логика, которой следует руководствоваться при использовании метода {@link |
| android.app.Activity#onActivityResult onActivityResult()} для обработки результата |
| выполнения операции. Первое условие проверяет, успешен ли запрос, и если он успешен, то результат для |
| {@code resultCode} будет {@link android.app.Activity#RESULT_OK}; также проверяется, известен ли запрос, |
| для которого получен этот результат, и в этом случае {@code requestCode} соответствует |
| второму параметру, отправленному в метод {@link android.app.Activity#startActivityForResult |
| startActivityForResult()}. Здесь код обрабатывает результат выполнения операции путем запроса данных, |
| возвращенных в {@link android.content.Intent} (параметр {@code data}).</p> |
| |
| <p>При этом {@link |
| android.content.ContentResolver} выполняет запрос к поставщику контента, который возвращает объект |
| {@link android.database.Cursor}, обеспечивающий считывание запрошенных данных. Дополнительные сведения представлены в статье |
| <a href="{@docRoot}guide/topics/providers/content-providers.html">Поставщики контента</a>.</p> |
| |
| <p>Дополнительные сведения об использовании намерений см. в статье <a href="{@docRoot}guide/components/intents-filters.html">Намерения и фильтры |
| намерений</a>.</p> |
| |
| |
| <h2 id="ShuttingDown">Завершение операции</h2> |
| |
| <p>Для завершения операции достаточно вызвать ее метод {@link android.app.Activity#finish |
| finish()}. Также для завершения отдельной операции, запущенной ранее, можно вызвать метод |
| {@link android.app.Activity#finishActivity finishActivity()}.</p> |
| |
| <p class="note"><strong>Примечание.</strong> В большинстве случаев вам не следует явно завершать операцию |
| с помощью этих методов. Как указано в следующем разделе, посвященном управлению жизненным циклом операции, система |
| Android выполняет такое управление за вас, поэтому вам не нужно завершать ваши |
| собственные операции. Вызов этих методов может отрицательно сказаться на ожидаемом |
| поведении приложения. Их следует использовать исключительно тогда, когда вы абсолютно не хотите, чтобы пользователь возвращался к этому |
| экземпляру операции.</p> |
| |
| |
| <h2 id="Lifecycle">Управление жизненным циклом операций</h2> |
| |
| <p>Управление жизненным циклом операций путем реализации методов обратного вызова |
| имеет важное значение при разработке надежных |
| и гибких приложений. На жизненный цикл операции напрямую влияют его связи |
| с другими операциями, его задачами и стеком переходов назад.</p> |
| |
| <p>Существует всего три состояния операции:</p> |
| |
| <dl> |
| <dt><i>Возобновлена</i></dt> |
| <dd>Операция выполняется на переднем плане экрана и отображается для пользователя. (Это состояние |
| также иногда называется «Выполняется».)</dd> |
| |
| <dt><i>Приостановлена</i></dt> |
| <dd>На переднем фоне выполняется другая операция, которая отображается для пользователя, однако эта операция по-прежнему не скрыта. То есть |
| поверх текущей операции отображается другая операция, частично прозрачная или не занимающая |
| полностью весь экран. Приостановленная операция полностью активна (объект {@link android.app.Activity} |
| по-прежнему находится в памяти, в нем сохраняются все сведения о состоянии и информация об элементах, и он также остается связанным с |
| диспетчером окон), однако в случае острой нехватки памяти система может завершить ее.</dd> |
| |
| <dt><i>Остановлена</i></dt> |
| <dd>Операция полностью перекрывается другой операцией (теперь она выполняется в |
| фоновом режиме). Остановленная операция по-прежнему активна (объект {@link android.app.Activity} |
| по-прежнему находится в памяти, в нем сохраняются все сведения о состоянии и информация об элементах, но объект больше <em>не</em> |
| связан с диспетчером окон). Однако операция больше не видна пользователю, и в случае нехватки памяти система |
| может завершить ее.</dd> |
| </dl> |
| |
| <p>Если операция приостановлена или полностью остановлена, система может очистить ее из памяти путем |
| завершения самой операции (с помощью метода {@link android.app.Activity#finish finish()}) или просто завершить ее |
| процесс. В случае повторного открытия операции (после ее завершения) ее потребуется создать |
| полностью.</p> |
| |
| |
| |
| <h3 id="ImplementingLifecycleCallbacks">Реализация обратных вызовов жизненного цикла</h3> |
| |
| <p>При переходе операции из одного вышеописанного состояния в другое, уведомления об этом |
| реализуются через различные методы обратного вызова. Все методы обратного вызова представляют собой привязки, которые |
| можно переопределить для выполнения подходящего действия при изменении состояния операции. Указанная ниже базовая |
| операция включает каждый из основных методов жизненного цикла.</p> |
| |
| |
| <pre> |
| public class ExampleActivity extends Activity { |
| @Override |
| public void {@link android.app.Activity#onCreate onCreate}(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| // The activity is being created. |
| } |
| @Override |
| protected void {@link android.app.Activity#onStart onStart()} { |
| super.onStart(); |
| // The activity is about to become visible. |
| } |
| @Override |
| protected void {@link android.app.Activity#onResume onResume()} { |
| super.onResume(); |
| // The activity has become visible (it is now "resumed"). |
| } |
| @Override |
| protected void {@link android.app.Activity#onPause onPause()} { |
| super.onPause(); |
| // Another activity is taking focus (this activity is about to be "paused"). |
| } |
| @Override |
| protected void {@link android.app.Activity#onStop onStop()} { |
| super.onStop(); |
| // The activity is no longer visible (it is now "stopped") |
| } |
| @Override |
| protected void {@link android.app.Activity#onDestroy onDestroy()} { |
| super.onDestroy(); |
| // The activity is about to be destroyed. |
| } |
| } |
| </pre> |
| |
| <p class="note"><strong>Примечание.</strong> При реализации этих методов жизненного цикла |
| всегда вызывайте реализацию суперкласса, прежде чем выполнять какие-либо действия, как показано в примерах выше.</p> |
| |
| <p>Вместе все эти методы определяют весь жизненный цикл операции. С помощью реализации этих |
| методов можно отслеживать три вложенных цикла в жизненном цикле операции: </p> |
| |
| <ul> |
| <li><b>Весь жизненный цикл</b> операции происходит между вызовом метода {@link |
| android.app.Activity#onCreate onCreate()} и вызовом метода {@link |
| android.app.Activity#onDestroy}. Ваша операция должна выполнить настройку |
| «глобального» состояния (например, определение макета) в методе {@link android.app.Activity#onCreate onCreate()}, а затем |
| освободить все оставшиеся в {@link android.app.Activity#onDestroy} ресурсы. Например, если в вашей операции |
| имеется поток, выполняющийся в фоновом режиме, для загрузки данных по сети, операция может создать |
| такой поток в методе {@link android.app.Activity#onCreate onCreate()}, а затем остановить его в методе {@link |
| android.app.Activity#onDestroy}.</li> |
| |
| <li><p><b>Видимый жизненный цикл</b> операции происходит между вызовами методов {@link |
| android.app.Activity#onStart onStart()} и {@link |
| android.app.Activity#onStop onStop()}. В течение этого времени операция |
| отображается на экране, где пользователь может взаимодействовать с ней. Например, метод {@link android.app.Activity#onStop onStop()} вызывается в |
| случае, когда запускается новая операция, а текущая больше не отображается. В промежутке между вызовами этих двух методов можно |
| сохранить ресурсы, необходимые для отображения операции для пользователя. Например, можно зарегистрировать объект |
| {@link android.content.BroadcastReceiver} в методе {@link |
| android.app.Activity#onStart onStart()} для отслеживания изменений, влияющих на пользовательский интерфейс, а затем отменить его регистрацию |
| в методе {@link android.app.Activity#onStop onStop()}, когда пользователь больше не видит |
| отображаемого. В течение всего жизненного цикла операции система может несколько раз вызывать методы {@link android.app.Activity#onStart onStart()} и {@link |
| android.app.Activity#onStop onStop()}, поскольку |
| операция то отображается для пользователя, то скрывается от него.</p></li> |
| |
| <li><p><b>Жизненный цикл операции, выполняемый на переднем плане</b>, происходит между вызовами методов {@link |
| android.app.Activity#onResume onResume()} и {@link android.app.Activity#onPause |
| onPause()}. В течение этого времени операция выполняется на фоне всех прочих операций и |
| отображается для пользователя. Операция может часто уходить в фоновый режим и выходить из него — например, |
| метод {@link android.app.Activity#onPause onPause()} вызывается при переходе устройства в спящий режим или |
| при появлении диалогового окна. Поскольку переход в это состояние может выполняться довольно часто, код в этих двух методах |
| должен быть легким, чтобы не допустить медленных переходов и не заставлять пользователя ждать.</p></li> |
| </ul> |
| |
| <p>На рисунке 1 иллюстрируются проходы и пути, которые операция может пройти между состояниями. |
| Прямоугольниками обозначены методы обратного вызова, которые можно реализовать для выполнения действий между переходами операции из одного |
| состояния в другое. <p> |
| |
| <img src="{@docRoot}images/activity_lifecycle.png" alt="" /> |
| <p class="img-caption"><strong>Рисунок 1.</strong> Жизненный цикл операции.</p> |
| |
| <p>Эти же методы жизненного цикла перечислены в таблице 1, в которой подробно описан каждый метод |
| обратного вызова и указано его место в |
| жизненном цикле операции в целом, включая сведения о том, может ли система завершить операцию по завершении |
| метода обратного вызова.</p> |
| |
| <p class="table-caption"><strong>Таблица 1.</strong> Сводные сведения о методах обратного вызова |
| жизненного цикла операции.</p> |
| |
| <table border="2" width="85%" frame="hsides" rules="rows"> |
| <colgroup align="left" span="3"></colgroup> |
| <colgroup align="left"></colgroup> |
| <colgroup align="center"></colgroup> |
| <colgroup align="center"></colgroup> |
| |
| <thead> |
| <tr><th colspan="3">Метод</th> <th>Описание</th> <th>Завершаемый?</th> <th>Следующий</th></tr> |
| </thead> |
| |
| <tbody> |
| <tr> |
| <td colspan="3" align="left"><code>{@link android.app.Activity#onCreate onCreate()}</code></td> |
| <td>Вызывается при первом создании операции. |
| Здесь необходимо настроить все обычные статические элементы — |
| создать представления, привязать данные и т. д. Этот метод передает |
| объект Bundle, содержащий предыдущее состояние операции (если |
| такое состояние было зафиксировано ранее; см. раздел <a href="#actstate">Сохранение состояния |
| операции</a>). |
| <p>За ним всегда следует метод {@code onStart()}.</p></td> |
| <td align="center">Нет</td> |
| <td align="center">{@code onStart()}</td> |
| </tr> |
| |
| <tr> |
| <td rowspan="5" style="border-left: none; border-right: none;"> </td> |
| <td colspan="2" align="left"><code>{@link android.app.Activity#onRestart |
| onRestart()}</code></td> |
| <td>Вызывается после остановки операции непосредственно перед ее |
| повторным запуском. |
| <p>За ним всегда следует метод {@code onStart()}.</p></td> |
| <td align="center">Нет</td> |
| <td align="center">{@code onStart()}</td> |
| </tr> |
| |
| <tr> |
| <td colspan="2" align="left"><code>{@link android.app.Activity#onStart onStart()}</code></td> |
| <td>Вызывается непосредственно перед тем, как операция становится видимой для пользователя. |
| <p>За ним следует метод {@code onResume()}, если операция |
| переходит на передний план, или метод {@code onStop()}, если она становится скрытой.</p></td> |
| <td align="center">Нет</td> |
| <td align="center">{@code onResume()} <br/>или<br/> {@code onStop()}</td> |
| </tr> |
| |
| <tr> |
| <td rowspan="2" style="border-left: none;"> </td> |
| <td align="left"><code>{@link android.app.Activity#onResume onResume()}</code></td> |
| <td>Вызывается непосредственно перед тем, как операция |
| начинает взаимодействие с пользователем. На этом этапе операция находится в самом |
| верху стека операций, и в нее поступают данные, вводимые пользователем. |
| <p>За ним всегда следует метод {@code onPause()}.</p></td> |
| <td align="center">Нет</td> |
| <td align="center">{@code onPause()}</td> |
| </tr> |
| |
| <tr> |
| <td align="left"><code>{@link android.app.Activity#onPause onPause()}</code></td> |
| <td>Вызывается, когда система собирается возобновить |
| другую операцию. Этот метод обычно используется для записи несохраненных изменений |
| в постоянное место хранения данных, остановки анимаций и других элементов, которые могут |
| использовать ресурсы ЦП и т. д. Здесь крайне важна оперативность, поскольку |
| следующая операция не будет возобновлена до тех пор, пока она не будет возвращена на передний план. |
| <p>За ним следует либо метод {@code onResume()}, если операция |
| возвращается на передний план, либо метод {@code onStop()}, если операция |
| становится скрытой для пользователя.</td> |
| <td align="center"><strong style="color:#800000">Да</strong></td> |
| <td align="center">{@code onResume()} <br/>или<br/> {@code onStop()}</td> |
| </tr> |
| |
| <tr> |
| <td colspan="2" align="left"><code>{@link android.app.Activity#onStop onStop()}</code></td> |
| <td>Вызывается в случае, когда операция больше не отображается для пользователя. Это может |
| произойти по причине того, что операция уничтожена, или ввиду возобновления поверх нее другой операции |
| (существующей или новой). |
| <p>За ним следует либо метод {@code onRestart()}, если |
| операция возобновляет взаимодействие с пользователем, либо метод |
| {@code onDestroy()}, если операция переходит в фоновый режим.</p></td> |
| <td align="center"><strong style="color:#800000">Да</strong></td> |
| <td align="center">{@code onRestart()} <br/>или<br/> {@code onDestroy()}</td> |
| </tr> |
| |
| <tr> |
| <td colspan="3" align="left"><code>{@link android.app.Activity#onDestroy |
| onDestroy()}</code></td> |
| <td>Вызывается перед тем, как операция будет уничтожена. Это финальный вызов, |
| который получает операция. Его можно вызвать либо по причине |
| завершения операции (вызов метода <code>{@link android.app.Activity#finish |
| finish()}</code>), либо ввиду временного уничтожения системой этого |
| экземпляра операции с целью освободить место. Чтобы различить эти два |
| сценария, используется метод <code>{@link |
| android.app.Activity#isFinishing isFinishing()}</code>.</td> |
| <td align="center"><strong style="color:#800000">Да</strong></td> |
| <td align="center"><em>Ничего</em></td> |
| </tr> |
| </tbody> |
| </table> |
| |
| <p>В столбце «Завершаемый?» указывается, может ли система |
| в любое время завершить процесс, содержащий операцию, <em>после возвращения метода</em> без |
| выполнения другой строки кода операции. Для трех методов в этом столбце указано «Да»: ({@link |
| android.app.Activity#onPause |
| onPause()}, {@link android.app.Activity#onStop onStop()} и {@link android.app.Activity#onDestroy |
| onDestroy()}). Поскольку метод {@link android.app.Activity#onPause onPause()} является первым из |
| этих трех после создания операции, метод {@link android.app.Activity#onPause onPause()} является |
| последним, который гарантированно будет вызван перед тем, как процесс <em>можно будет</em> завершить; если |
| системе потребуется срочно восстановить память в случае аварийной ситуации, то методы {@link |
| android.app.Activity#onStop onStop()} и {@link android.app.Activity#onDestroy onDestroy()} вызвать |
| не удастся. Поэтому следует воспользоваться {@link android.app.Activity#onPause onPause()}, чтобы записать |
| критически важные данные (такие как правки пользователя) в хранилище постоянных данных. Однако следует внимательно подходить к выбору информации, |
| которую необходимо сохранить во время выполнения метода {@link android.app.Activity#onPause onPause()}, поскольку любая блокировка |
| процедур в этом методе может вызвать блокирование перехода к следующей операции и тормозить работу |
| пользователя.</p> |
| |
| <p> Методы, для которых в столбце <b>Завершаемый?</b> указано «Нет», защищают процесс, содержащий операцию |
| , от завершения сразу с момента их вызова. Поэтому завершить операцию |
| можно в период между возвратом {@link android.app.Activity#onPause onPause()} и вызовом |
| {@link android.app.Activity#onResume onResume()}. Его снова не удастся завершить, пока снова не будет вызван и возвращен |
| {@link android.app.Activity#onPause onPause()}. </p> |
| |
| <p class="note"><strong>Примечание.</strong> Операцию, которую технически невозможно завершить в соответствии с определением |
| в таблице 1, по-прежнему может завершить система, однако это может произойти только в |
| чрезвычайных ситуациях, когда нет другой возможности. Случаи, когда возможно завершение операции, |
| более подробно рассматриваются в статье<a href="{@docRoot}guide/components/processes-and-threads.html">Процессы и |
| потоки</a>.</p> |
| |
| |
| <h3 id="SavingActivityState">Сохранение состояния операции</h3> |
| |
| <p>В обзорных сведениях об <a href="#Lifecycle">управлении жизненным циклом операции</a> кратко упоминается, |
| что |
| в случае приостановки или полной остановки операции ее состояние сохраняется. Это действительно так, поскольку |
| объект {@link android.app.Activity} при этом по-прежнему находится в памяти |
| , и вся информация о ее элементах и текущем состоянии по-прежнему активна. Поэтому любые |
| вносимые пользователем в операции изменения сохраняются, и когда операция возвращается на передний план |
| (когда она «возобновляется»), эти изменения остаются в этом объекте.</p> |
| |
| <p>Однако когда система уничтожает операцию в целях восстановления памяти, объект {@link |
| android.app.Activity} уничтожается, в результате чего системе не удается просто восстановить состояние операции для взаимодействия |
| с ней. Вместо этого системе необходимо повторно создать объект {@link android.app.Activity}, если пользователь |
| возвращается к нему. Но пользователю неизвестно, |
| что система уже уничтожила операцию и создала ее повторно, поэтому, возможно, |
| он ожидает, что операция осталась прежней. В этой ситуации можно обеспечить |
| сохранение важной информации о состоянии операции путем реализации дополнительного |
| метода обратного вызова, который позволяет сохранить информацию о вашей операции: {@link |
| android.app.Activity#onSaveInstanceState onSaveInstanceState()}.</p> |
| |
| <p>Прежде чем сделать операцию доступной для уничтожения, система вызывает метод |
| {@link android.app.Activity#onSaveInstanceState onSaveInstanceState()}. Система передает в этот метод объект |
| {@link android.os.Bundle}, в котором можно сохранить |
| информацию о состоянии операции в виде пар «имя-значение», используя для этого такие методы, как {@link |
| android.os.Bundle#putString putString()} и {@link |
| android.os.Bundle#putInt putInt()}. Затем, если система завершает процесс |
| вашего приложения и пользователь возвращается к вашей операции, система повторно создает операцию и передает объект |
| {@link android.os.Bundle} в оба метода: {@link android.app.Activity#onCreate onCreate()} и {@link |
| android.app.Activity#onRestoreInstanceState onRestoreInstanceState()}. С помощью любого из этих |
| методов можно извлечь из объекта {@link android.os.Bundle} сохраненную информацию о состоянии операции и восстановить |
| ее. Если такая информация отсутствует, то объект {@link |
| android.os.Bundle} передается с нулевым значением (это происходит в случае, когда операция |
| создается в первый раз).</p> |
| |
| <img src="{@docRoot}images/fundamentals/restore_instance.png" alt="" /> |
| <p class="img-caption"><strong>Рисунок 2.</strong> Два способа возврата операции к отображению для пользователя |
| в неизмененном состоянии: уничтожение операции с последующим ее повторным созданием, когда операция должна восстановить свое |
| ранее сохраненное состояние, или остановка операции и ее последующее восстановление в неизмененном |
| состоянии.</p> |
| |
| <p class="note"><strong>Примечание.</strong> Нет никаких гарантий, что метод {@link |
| android.app.Activity#onSaveInstanceState onSaveInstanceState()} будет вызван до того, как ваша |
| операция будет уничтожена, поскольку существуют случаи, когда нет необходимости сохранять состояние |
| (например, когда пользователь покидает вашу операцию нажатием кнопки <em>Назад</em>, |
| явным образом |
| закрывая ее). Если система вызывает метод {@link android.app.Activity#onSaveInstanceState |
| onSaveInstanceState()}, она делает это до вызова метода {@link |
| android.app.Activity#onStop onStop()} и, возможно, перед вызовом метода {@link android.app.Activity#onPause |
| onPause()}.</p> |
| |
| <p>Однако, даже если вы ничего не предпринимаете и не реализуете метод {@link |
| android.app.Activity#onSaveInstanceState onSaveInstanceState()}, часть состояния операции восстанавливается |
| реализацией по умолчанию метода {@link |
| android.app.Activity#onSaveInstanceState onSaveInstanceState()} класса {@link android.app.Activity}. В частности, реализация |
| по умолчанию вызывает соответствующий метод {@link |
| android.view.View#onSaveInstanceState onSaveInstanceState()} для каждого объекта {@link |
| android.view.View} в макете, благодаря чему каждое представление может предоставлять ту информацию о себе, |
| которую следует сохранить. Почти каждый виджет в платформе Android реализует этот метод необходимым |
| для себя способом так, что любые видимые изменения в пользовательском интерфейсе автоматически сохраняются и восстанавливаются при повторном |
| создании операции. Например, виджет {@link android.widget.EditText} сохраняет любой текст, |
| введенный пользователем, а виджет {@link android.widget.CheckBox} сохраняет информацию о том, был |
| ли установлен флажок. От вас требуется лишь указать уникальный идентификатор (с атрибутом <a href="{@docRoot}guide/topics/resources/layout-resource.html#idvalue">{@code android:id}</a>) |
| для каждого виджета, состояние которого необходимо сохранить. Если виджету не присвоен идентификатор, то системе |
| не удастся сохранить его состояние.</p> |
| |
| <div class="sidebox-wrapper"> |
| <div class="sidebox"> |
| <p>Вы также можете явно отключить сохранение информации о состоянии представления в макете. Для этого задайте для атрибута |
| {@link android.R.attr#saveEnabled android:saveEnabled} значение {@code "false"} или вызовите метод |
| {@link android.view.View#setSaveEnabled setSaveEnabled()}. Обычно отключать сохранение такой информации не требуется |
| , однако это может потребоваться в случаях, когда восстановить состояние пользовательского интерфейса операции необходимо другим образом.</p> |
| </div> |
| </div> |
| |
| <p>Несмотря на то что реализация метода {@link |
| android.app.Activity#onSaveInstanceState onSaveInstanceState()} по умолчанию позволяет сохранить полезную информацию о |
| пользовательском интерфейсе вашей операции, вам по-прежнему может потребоваться переопределить ее для сохранения дополнительной информации. |
| Например, может потребоваться сохранить значения элементов, которые изменялись в течение жизненного цикла операции (которые могут |
| коррелировать со значениями, восстановленными в пользовательском интерфейсе, однако элементы, содержащие эти значения пользовательского интерфейса, по умолчанию не |
| были восстановлены).</p> |
| |
| <p>Поскольку реализация метода {@link |
| android.app.Activity#onSaveInstanceState onSaveInstanceState()} по умолчанию позволяет сохранить состояние пользовательского интерфейса, в случае |
| , если вы переопределите метод с целью сохранить дополнительную информацию о состоянии, перед выполнением каких-либо действий вы всегда можете вызвать реализацию |
| суперкласса для метода |
| {@link android.app.Activity#onSaveInstanceState onSaveInstanceState()}. Точно так же реализацию суперкласса {@link |
| android.app.Activity#onRestoreInstanceState onRestoreInstanceState()} следует вызывать в случае ее переопределения, чтобы реализация по умолчанию могла сохранить |
| состояния представлений.</p> |
| |
| <p class="note"><strong>Примечание.</strong> Поскольку вызов метода {@link android.app.Activity#onSaveInstanceState |
| onSaveInstanceState()} не гарантируется, |
| вам следует использовать его только для записи переходного состояния операции (состояние |
| пользовательского интерфейса) — никогда не используйте его для хранения постоянных данных. Вместо этого используйте метод {@link |
| android.app.Activity#onPause onPause()} для сохранения постоянных данных (например, тех, которые следует сохранить в |
| базу данных), когда пользователь покидает операцию.</p> |
| |
| <p>Отличный способ проверить возможность вашего приложения восстанавливать свое состояние — это просто повернуть |
| устройство для изменения ориентации экрана. При изменении ориентации экрана система |
| уничтожает и повторно создает операцию, чтобы применить альтернативные ресурсы, которые могут быть |
| доступны для новой конфигурации экрана. Только по одной этой причине крайне важно, чтобы ваша операция |
| могла полностью восстанавливать свое состояние при ее повторном создании, поскольку пользователи постоянно работают с |
| приложениями в разных ориентациях экрана.</p> |
| |
| |
| <h3 id="ConfigurationChanges">Обработка изменений в конфигурации</h3> |
| |
| <p>Некоторые конфигурации устройств могут изменяться в режиме выполнения |
| (например, ориентация экрана, доступность клавиатуры и язык). В таких случаях Android повторно создает выполняющуюся операцию |
| (система сначала вызывает метод {@link android.app.Activity#onDestroy}, а затем сразу же вызывает метод {@link |
| android.app.Activity#onCreate onCreate()}). Такое поведение позволяет |
| приложению учитывать новые конфигурации путем автоматической перезагрузки в приложение |
| альтернативных ресурсов, которые вы предоставили (например, различные макеты для |
| разных ориентаций и экранов разных размеров).</p> |
| |
| <p>Если операция разработана должным образом и должным образом поддерживает перезапуск после изменения ориентации экрана и |
| восстановление своего состояния, как описано выше, ваше приложение можно считать более устойчивым к другим |
| непредвиденным событиям в жизненном цикле операции.</p> |
| |
| <p>Лучший способ обработки такого перезапуска |
| — сохранить и восстановить состояние операции с помощью методов {@link |
| android.app.Activity#onSaveInstanceState onSaveInstanceState()} и {@link |
| android.app.Activity#onRestoreInstanceState onRestoreInstanceState()} (или {@link |
| android.app.Activity#onCreate onCreate()}), как описано в предыдущем разделе.</p> |
| |
| <p>Дополнительные сведения об изменениях конфигурации, происходящих в режиме выполнения, и о способах их обработки |
| представлены в руководстве<a href="{@docRoot}guide/topics/resources/runtime-changes.html">Обработка изменений в режиме |
| выполнения</a>.</p> |
| |
| |
| |
| <h3 id="CoordinatingActivities">Согласование операций</h3> |
| |
| <p>Когда одна операция запускает другую, в жизненных циклах обеих из них происходит переход из одного состояния в другое. Первая операция |
| приостанавливается и заврешается (однако она не будет остановлена, если она по-прежнему видима на фоне), а вторая |
| операция создается. В случае, если эти операции обмениваются данным, сохраненными на диске или в другом месте, важно понимать, |
| что первая операция не останавливается полностью до тех пор, пока не будет создана вторая операция. |
| Наоборот, процесс запуска второй операции накладывается на процесс остановки первой |
| операции.</p> |
| |
| <p>Порядок обратных вызовов жизненного цикла четко определен, в частности, когда в одном и том же процессе находятся две операции |
| , и одна из них запускает другую. Ниже представлен порядок выполнения действий в случае, когда операция |
| А запускает операцию Б. </p> |
| |
| <ol> |
| <li>Выполняется метод {@link android.app.Activity#onPause onPause()} операции А.</li> |
| |
| <li>Последовательно выполняются методы {@link android.app.Activity#onCreate onCreate()}, {@link |
| android.app.Activity#onStart onStart()} и {@link android.app.Activity#onResume onResume()} |
| операции Б. (Теперь для пользователя отображается операция Б.)</li> |
| |
| <li>Затем, если операция A больше не отображается на экране, выполняется ее метод {@link |
| android.app.Activity#onStop onStop()}.</li> |
| </ol> |
| |
| <p>Такая предсказуемая последовательность выполнения обратных вызовов жизненного цикла позволяет управлять переходом |
| информации из одной операции в другую. Например, если после остановки первой операции требуется выполнить запись в базу данных, |
| чтобы следующая операция могла считать их, то запись в базу данных следует выполнить |
| во время выполнения метода {@link android.app.Activity#onPause onPause()}, а не во время выполнения метода {@link |
| android.app.Activity#onStop onStop()}.</p> |
| |
| <!-- |
| <h2>Beginner's Path</h2> |
| |
| <p>For more information about how Android maintains a history of activities and |
| enables user multitasking, continue with the <b><a |
| href="{@docRoot}guide/components/tasks-and-back-stack.html">Tasks and Back |
| Stack</a></b> document.</p> |
| --> |