1. Ласкаво просимо
Ця практична код-лабораторія є частиною Розділу 1: Початок роботи в курсі Основ розробника Android (версія 2). Ви отримаєте найбільшу користь від цього курсу, якщо будете працювати над кодовими лабораторіями в послідовності:
- Щоб отримати повний перелік кодових робіт у курсі, перегляньте Codelabs для Android Developer Fundamentals (V2).
- Докладні відомості про курс, включаючи посилання на всі концептуальні розділи, програми та слайди, див. в Основах розробника Android (версія 2).
вступ
У цій практиці ви дізнаєтеся більше про життєвий цикл діяльності. Життєвий цикл — це набір станів, у яких може перебувати активність протягом усього життєвого циклу, від моменту створення до моменту знищення, коли система повертає свої ресурси. Коли користувач переходить між діями у вашій програмі (а також у вашій програмі та з неї), дії переходять між різними станами у своєму життєвому циклі.
Кожен етап у життєвому циклі дії має відповідний метод зворотного виклику: onCreate(), onStart(), onPause() і так далі. Коли дія змінює стан, викликається відповідний метод зворотного виклику. Ви вже бачили один із цих методів: onCreate(). Замінивши будь-який із методів зворотного виклику життєвого циклу у ваших класах Activity, ви можете змінити поведінку активності за замовчуванням у відповідь на дії користувача чи системи.
Стан активності також може змінюватися у відповідь на зміни конфігурації пристрою, наприклад, коли користувач обертає пристрій із книжкової в альбомну. Коли відбуваються ці зміни конфігурації, діяльність знищується та відтворюється у стані за замовчуванням, і користувач може втратити інформацію, яку він ввів у дії. Щоб не заплутувати своїх користувачів, важливо розробити програму, щоб запобігти неочікуваній втраті даних. Далі в цій практичній програмі ви експериментуєте зі змінами конфігурації та дізнаєтесь, як зберегти стан активності у відповідь на зміни конфігурації пристрою та інші події життєвого циклу діяльності.
У цій практиці ви додаєте оператори журналювання до програми TwoActivities і спостерігаєте за змінами життєвого циклу діяльності під час використання програми. Потім ви починаєте працювати з цими змінами та досліджувати, як обробляти дані користувача за цих умов.
передумови
Ви повинні вміти:
- Створіть і запустіть проект програми в Android Studio .
- Додайте оператори журналу до своєї програми та переглядайте ці журнали на панелі Logcat.
- Розумійте та працюйте з Діяльністю та Наміром, а також відчувайте комфорт у взаємодії з ними.
Що ви дізнаєтеся
- Як працює життєвий цикл активності.
- Коли активність починається, припиняється, зупиняється та знищується.
- Про методи зворотного виклику життєвого циклу, пов’язані зі змінами активності.
- Наслідки дій (наприклад, зміни конфігурації), які можуть призвести до подій життєвого циклу активності.
- Як зберегти стан активності протягом подій життєвого циклу.
Що ти зробиш
- Додайте код до програми TwoActivities із попередньої практики, щоб реалізувати різні зворотні виклики життєвого циклу Activity, щоб включити оператори журналювання.
- Спостерігайте за змінами стану під час роботи вашої програми та під час взаємодії з кожною діяльністю у вашій програмі.
- Змініть свою програму, щоб зберегти стан екземпляра активності, яка несподівано відтворюється у відповідь на поведінку користувача або зміну конфігурації на пристрої.
2. Огляд програми
У цій практиці ви додаєте до програми TwoActivities . Програма виглядає та поводиться приблизно так само, як і в останній кодовій роботі. Він містить дві реалізації Activity і дає користувачеві можливість надсилати між ними. Зміни, які ви вносите в програму під час цієї практики, не вплинуть на її видиму поведінку користувача.
3. 3. Завдання 1: Додайте зворотні виклики життєвого циклу до TwoActivities
У цьому завданні ви реалізуєте всі методи зворотного виклику життєвого циклу Activity для друку повідомлень у logcat, коли ці методи викликаються. Ці повідомлення журналу дозволять вам побачити, коли змінюється стан життєвого циклу активності та як ці зміни стану життєвого циклу впливають на вашу програму під час її роботи.
1.1 (Необов’язково) Скопіюйте проект TwoActivities
Для виконання завдань у цій практиці ви зміните існуючий проект TwoActivities , створений під час останньої практики. Якщо ви бажаєте зберегти попередній проект TwoActivities без змін, виконайте кроки в Додатку: Службові програми , щоб створити копію проекту.
1.2 Впровадити зворотні виклики в MainActivity
- Відкрийте проект TwoActivities в Android Studio та відкрийте MainActivity на панелі «Проект» > «Android».
- У метод onCreate() додайте такі оператори журналу:
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
- Додайте перевизначення для зворотного виклику onStart() із оператором у журнал для цієї події:
@Override
public void onStart(){
super.onStart();
Log.d(LOG_TAG, "onStart");
}
Для ярлика виберіть «Код» > «Замінити методи» в Android Studio. З’явиться діалогове вікно з усіма можливими методами, які ви можете змінити у своєму класі. Вибір одного або кількох методів зворотного виклику зі списку вставляє повний шаблон для цих методів, включаючи необхідний виклик суперкласу.
- Використовуйте метод onStart() як шаблон для реалізації зворотних викликів життєвого циклу onPause(), onRestart(), onResume(), onStop() і onDestroy().
Усі методи зворотного виклику мають однакові підписи (за винятком імені). Якщо ви копіюєте та вставляєте onStart(), щоб створити ці інші методи зворотного виклику, не забудьте оновити вміст, щоб викликати правильний метод у суперкласі та зареєструвати правильний метод.
- Запустіть свою програму.
- Натисніть вкладку Logcat внизу Android Studio, щоб відобразити панель Logcat. Ви повинні побачити три повідомлення журналу, що показують три стани життєвого циклу, через які дія перейшла під час її початку:
D/MainActivity: -------
D/MainActivity: onCreate
D/MainActivity: onStart
D/MainActivity: onResume
1.3 Впровадити зворотні виклики життєвого циклу в SecondActivity
Тепер, коли ви реалізували методи зворотного виклику життєвого циклу для MainActivity, зробіть те саме для SecondActivity.
- Відкрийте SecondActivity.
- У верхній частині класу додайте константу для змінної LOG_TAG:
private static final String LOG_TAG = SecondActivity.class.getSimpleName();
- Додайте зворотні виклики життєвого циклу та оператори журналу до другої дії. (Ви можете скопіювати та вставити методи зворотного виклику з MainActivity.)
- Додайте оператор журналу до методу returnReply() безпосередньо перед методом finish():
Log.d(LOG_TAG, "End SecondActivity");
1.4 Спостерігайте за журналом під час роботи програми**
- Запустіть свою програму.
- Натисніть вкладку Logcat внизу Android Studio, щоб відобразити панель Logcat.
- Введіть Діяльність у вікні пошуку. Android logcat може бути дуже довгим і захаращеним. Оскільки змінна LOG_TAG у кожному класі містить слова MainActivity або SecondActivity, це ключове слово дозволяє фільтрувати журнал лише за тим, що вас цікавить.
Експериментуйте зі своїм додатком і зверніть увагу на події життєвого циклу, які відбуваються у відповідь на різні дії. Зокрема, спробуйте такі речі:
- Використовуйте програму як зазвичай (надішліть повідомлення, дайте відповідь іншим повідомленням).
- Використовуйте кнопку «Назад», щоб повернутися від другої дії до основної.
- Використовуйте стрілку вгору на панелі програми, щоб повернутися від другої дії до основної.
- Обертайте пристрій як на основній, так і на другій активності в різний час у вашій програмі та спостерігайте, що відбувається в * журналі та на екрані.
- Натисніть кнопку огляду (квадратна кнопка праворуч від Home) і закрийте програму (торкніться X).
- Поверніться на головний екран і перезапустіть програму.
ПОРАДА. Якщо ви запускаєте свою програму в емуляторі, ви можете імітувати обертання за допомогою Control+F11 або Control+Function+F11.
Код розв’язку завдання 1
Наведені нижче фрагменти коду показують код рішення для першого завдання.
Основна діяльність
Наведені нижче фрагменти коду показують доданий код у MainActivity, але не весь клас.
Метод onCreate():
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Log the start of the onCreate() method.
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
// Initialize all the view variables.
mMessageEditText = findViewById(R.id.editText_main);
mReplyHeadTextView = findViewById(R.id.text_header_reply);
mReplyTextView = findViewById(R.id.text_message_reply);
}
Інші методи життєвого циклу:
@Override
protected void onStart() {
super.onStart();
Log.d(LOG_TAG, "onStart");
}
@Override
protected void onPause() {
super.onPause();
Log.d(LOG_TAG, "onPause");
}
@Override
protected void onRestart() {
super.onRestart();
Log.d(LOG_TAG, "onRestart");
}
@Override
protected void onResume() {
super.onResume();
Log.d(LOG_TAG, "onResume");
}
@Override
protected void onStop() {
super.onStop();
Log.d(LOG_TAG, "onStop");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(LOG_TAG, "onDestroy");
}
SecondActivity
Наступні фрагменти коду показують доданий код у SecondActivity, але не весь клас.
У верхній частині класу SecondActivity:
private static final String LOG_TAG = SecondActivity.class.getSimpleName();
Метод returnReply():
public void returnReply(View view) {
String reply = mReply.getText().toString();
Intent replyIntent = new Intent();
replyIntent.putExtra(EXTRA_REPLY, reply);
setResult(RESULT_OK, replyIntent);
Log.d(LOG_TAG, "End SecondActivity");
finish();
}
Інші методи життєвого циклу:
Те саме, що для MainActivity вище.
4. 4. Завдання 2: Збережіть та відновіть стан екземпляра Activity
Залежно від системних ресурсів і поведінки користувача кожна активність у вашій програмі може бути знищена та реконструйована набагато частіше, ніж ви думаєте.
Можливо, ви помітили цю поведінку в останньому розділі, коли обертали пристрій або емулятор. Обертання пристрою є одним із прикладів зміни конфігурації пристрою. Хоча ротація є найпоширенішою, усі зміни конфігурації призводять до знищення поточної активності та створення її заново, як якщо б вона була новою. Якщо ви не врахуєте таку поведінку у своєму коді, коли відбувається зміна конфігурації, ваш макет активності може повернутися до свого вигляду за замовчуванням і початкових значень, і ваші користувачі можуть втратити своє місце, дані або стан свого прогресу в ваш додаток.
Стан кожної активності зберігається як набір пар ключ/значення в об’єкті Bundle, що називається станом екземпляра активності. Система зберігає інформацію про стан за замовчуванням у пакеті стану екземпляра безпосередньо перед припиненням активності та передає цей пакет новому екземпляру активності для відновлення.
Щоб уникнути втрати даних у Activity, коли вони несподівано знищені та створені заново, вам потрібно реалізувати метод onSaveInstanceState(). Система викликає цей метод у вашій активності (між onPause() і onStop()), коли існує ймовірність, що дію може бути знищено та створено заново.
Дані, які ви зберігаєте в стані екземпляра, стосуються лише цього екземпляра цієї конкретної активності під час поточного сеансу програми. Коли ви зупиняєте та перезапускаєте новий сеанс програми, стан екземпляра Activity втрачається, і Activity повертається до свого вигляду за замовчуванням. Якщо вам потрібно зберігати дані користувача між сеансами програми, використовуйте спільні параметри або базу даних. Ви дізнаєтеся про обидва з них у наступному практичному занятті.
2.1 Збережіть стан екземпляра Activity за допомогою onSaveInstanceState()
Можливо, ви помітили, що обертання пристрою зовсім не впливає на стан другої активності. Це пов’язано з тим, що другий макет і стан активності генеруються з макета та наміру, який його активував. Навіть якщо Activity створено повторно, Intent все ще існує, і дані в цьому Intent все ще використовуються кожного разу, коли викликається метод onCreate() у другій Activity.
Крім того, ви можете помітити, що в кожній дії будь-який текст, який ви ввели в елементи повідомлення або відповіді EditText, зберігається навіть після повороту пристрою. Це пояснюється тим, що інформація про стан деяких елементів View у вашому макеті автоматично зберігається під час змін конфігурації, і поточне значення EditText є одним із таких випадків.
Тож єдиний стан Activity, який вас цікавить, — це елементи TextView для заголовка відповіді та текст відповіді в основній Activity. Обидва елементи TextView невидимі за замовчуванням; вони з’являються лише тоді, коли ви надсилаєте повідомлення назад до основної дії з другої дії.
У цьому завданні ви додаєте код для збереження стану екземпляра цих двох елементів TextView за допомогою onSaveInstanceState().
- Відкрийте MainActivity.
- Додайте цю скелетну реалізацію onSaveInstanceState() до дії або скористайтеся Кодом > Методи перевизначення, щоб вставити скелетну перевизначення.
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
- Перевірте, чи видимий заголовок наразі, і якщо так, помістіть цей стан видимості в пакет стану за допомогою методу putBoolean() і ключа «reply_visible».
if (mReplyHeadTextView.getVisibility() == View.VISIBLE) {
outState.putBoolean("reply_visible", true);
}
Пам’ятайте, що заголовок і текст відповіді позначено як невидимі, доки не буде відповіді від другої дії. Якщо заголовок видно, це означає, що є дані відповіді, які потрібно зберегти. Зауважте, що нас цікавить лише цей стан видимості — фактичний текст заголовка не потрібно зберігати, оскільки цей текст ніколи не змінюється.
- Усередині цієї самої перевірки додайте текст відповіді в пакет.
outState.putString("reply_text",mReplyTextView.getText().toString());
Якщо заголовок видно, ви можете припустити, що саме повідомлення відповіді також видно. Вам не потрібно перевіряти чи зберігати поточний стан видимості повідомлення-відповіді. Тільки фактичний текст повідомлення потрапляє в пакет стану з ключем "reply_text".
Ви зберігаєте стан лише тих елементів View, які можуть змінитися після створення Activity. Інші елементи View у вашій програмі (EditText, Button) можна будь-коли відтворити зі стандартного макета.
Зауважте, що система збереже стан деяких елементів View, наприклад вміст EditText.
2.2 Відновлення стану екземпляра Activity у onCreate()
Після того як ви зберегли стан екземпляра Activity, вам також потрібно відновити його під час повторного створення Activity. Ви можете зробити це або в onCreate(), або реалізувавши зворотний виклик onRestoreInstanceState(), який викликається після onStart() після створення Activity.
У більшості випадків найкращим місцем для відновлення стану активності є onCreate(), щоб гарантувати, що інтерфейс користувача, включно зі станом, стане доступним якомога швидше. Іноді зручно зробити це в onRestoreInstanceState() після завершення всієї ініціалізації або дозволити підкласам вирішити, чи використовувати вашу реалізацію за замовчуванням.
- У методі onCreate() після ініціалізації змінних View за допомогою findViewById() додайте перевірку, щоб переконатися, що savedInstanceState не дорівнює null.
// Initialize all the view variables.
mMessageEditText = findViewById(R.id.editText_main);
mReplyHeadTextView = findViewById(R.id.text_header_reply);
mReplyTextView = findViewById(R.id.text_message_reply);
// Restore the state.
if (savedInstanceState != null) {
}
Коли вашу дію створено, система передає пакет стану onCreate() як єдиний аргумент. Під час першого виклику onCreate() і запуску вашої програми Bundle стає нульовим — під час першого запуску вашої програми немає жодного стану. Подальші виклики onCreate() мають пакет, заповнений даними, які ви зберегли в onSaveInstanceState().
- Усередині цієї перевірки отримайте поточну видимість (true або false) із Bundle за допомогою ключа "reply_visible".
if (savedInstanceState != null) {
boolean isVisible =
savedInstanceState.getBoolean("reply_visible");
}
- Додайте перевірку під попереднім рядком для змінної isVisible.
if (isVisible) {
}
Якщо в пакеті стану є ключ reply_visible (і тому isVisible має значення true), вам потрібно буде відновити стан.
- Усередині тесту isVisible зробіть видимим заголовок.
mReplyHeadTextView.setVisibility(View.VISIBLE);
- Отримайте текстове повідомлення-відповідь із Bundle за допомогою ключа "reply_text" і налаштуйте TextView для відповіді, щоб показувати цей рядок.
mReplyTextView.setText(savedInstanceState.getString("reply_text"));
- Зробіть відповідь TextView також видимою:
mReplyTextView.setVisibility(View.VISIBLE);
- Запустіть програму. Спробуйте повернути пристрій або емулятор, щоб переконатися, що повідомлення відповіді (якщо воно є) залишається на екрані після повторного створення дії.
Код розв’язання завдання 2
Наведені нижче фрагменти коду показують код рішення для цього завдання.
Основна діяльність
Наведені нижче фрагменти коду показують доданий код у MainActivity, але не весь клас.
Метод onSaveInstanceState():
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// If the heading is visible, message needs to be saved.
// Otherwise we're still using default layout.
if (mReplyHeadTextView.getVisibility() == View.VISIBLE) {
outState.putBoolean("reply_visible", true);
outState.putString("reply_text",
mReplyTextView.getText().toString());
}
}
Метод onCreate():
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
// Initialize all the view variables.
mMessageEditText = findViewById(R.id.editText_main);
mReplyHeadTextView = findViewById(R.id.text_header_reply);
mReplyTextView = findViewById(R.id.text_message_reply);
// Restore the saved state.
// See onSaveInstanceState() for what gets saved.
if (savedInstanceState != null) {
boolean isVisible =
savedInstanceState.getBoolean("reply_visible");
// Show both the header and the message views. If isVisible is
// false or missing from the bundle, use the default layout.
if (isVisible) {
mReplyHeadTextView.setVisibility(View.VISIBLE);
mReplyTextView.setText(savedInstanceState
.getString("reply_text"));
mReplyTextView.setVisibility(View.VISIBLE);
}
}
}
Повний проект:
Проект Android Studio: TwoActivitiesLifecycle
5. Кодування
Завдання: створити просту програму зі списком покупок із основною діяльністю для списку, який створює користувач, і другою діяльністю для списку поширених товарів для покупок.
- Основна дія має містити список для створення, який має складатися з десяти порожніх елементів TextView.
- Кнопка «Додати товар» у основній дії запускає другу дію, яка містить список поширених товарів для покупок (сир, рис, яблука тощо). Використовуйте елементи Button для відображення елементів.
- Вибір елемента повертає користувача до основної дії та оновлює порожній TextView, щоб включити вибраний елемент.
Використовуйте намір для передачі інформації від однієї діяльності до іншої. Переконайтеся, що поточний стан списку покупок зберігається, коли користувач повертає пристрій.
6. Підведення підсумків
- Життєвий цикл активності — це набір станів, через які переміщується дія, починаючи з моменту її створення та закінчуючи, коли система Android відновлює ресурси для цієї дії.
- Коли користувач переходить від однієї дії до іншої, а також усередині та поза вашою програмою, кожна дія переходить між станами в життєвому циклі активності.
- Кожен стан у життєвому циклі Activity має відповідний метод зворотного виклику, який ви можете замінити у своєму класі Activity.
- Методами життєвого циклу є onCreate(), onStart(), onPause(), onRestart(), onResume(), onStop(), onDestroy().
- Заміна методу зворотного виклику життєвого циклу дозволяє вам додати поведінку, яка виникає, коли ваша діяльність переходить у цей стан.
- Ви можете додати скелетні методи заміни до своїх класів в Android Studio за допомогою «Код» > «Перевизначити».
- Зміни конфігурації пристрою, такі як обертання, призводять до того, що Activity знищується та створюється заново, ніби це було ново.
- Частина стану активності зберігається після зміни конфігурації, включаючи поточні значення елементів EditText. Для всіх інших даних ви повинні явно зберегти ці дані самостійно.
- Збережіть стан екземпляра Activity у методі onSaveInstanceState().
- Дані про стан екземпляра зберігаються як прості пари ключ/значення в наборі. Використовуйте методи Bundle, щоб додавати дані в Bundle і повертати дані з Bundle.
- Відновіть стан екземпляра за допомогою onCreate(), що є кращим способом, або onRestoreInstanceState(). Назад
1. Ласкаво просимо
Ця практична код-лабораторія є частиною Розділу 1: Початок роботи в курсі Основ розробника Android (версія 2). Ви отримаєте найбільшу користь від цього курсу, якщо будете працювати над кодовими лабораторіями в послідовності:
- Щоб отримати повний перелік кодових робіт у курсі, перегляньте Codelabs для Android Developer Fundamentals (V2).
- Докладні відомості про курс, включаючи посилання на всі концептуальні розділи, програми та слайди, див. в Основах розробника Android (версія 2).
вступ
У цій практиці ви дізнаєтеся більше про життєвий цикл діяльності. Життєвий цикл — це набір станів, у яких може перебувати активність протягом усього життєвого циклу, від моменту створення до моменту знищення, коли система повертає свої ресурси. Коли користувач переходить між діями у вашій програмі (а також у вашій програмі та з неї), дії переходять між різними станами у своєму життєвому циклі.
Кожен етап у життєвому циклі дії має відповідний метод зворотного виклику: onCreate(), onStart(), onPause() і так далі. Коли дія змінює стан, викликається відповідний метод зворотного виклику. Ви вже бачили один із цих методів: onCreate(). Замінивши будь-який із методів зворотного виклику життєвого циклу у ваших класах Activity, ви можете змінити поведінку активності за замовчуванням у відповідь на дії користувача чи системи.
Стан активності також може змінюватися у відповідь на зміни конфігурації пристрою, наприклад, коли користувач обертає пристрій із книжкової в альбомну. Коли відбуваються ці зміни конфігурації, діяльність знищується та відтворюється у стані за замовчуванням, і користувач може втратити інформацію, яку він ввів у дії. Щоб не заплутувати своїх користувачів, важливо розробити програму, щоб запобігти неочікуваній втраті даних. Далі в цій практичній програмі ви експериментуєте зі змінами конфігурації та дізнаєтесь, як зберегти стан активності у відповідь на зміни конфігурації пристрою та інші події життєвого циклу діяльності.
У цій практиці ви додаєте оператори журналювання до програми TwoActivities і спостерігаєте за змінами життєвого циклу діяльності під час використання програми. Потім ви починаєте працювати з цими змінами та досліджувати, як обробляти дані користувача за цих умов.
передумови
Ви повинні вміти:
- Створіть і запустіть проект програми в Android Studio .
- Додайте оператори журналу до своєї програми та переглядайте ці журнали на панелі Logcat.
- Розумійте та працюйте з Діяльністю та Наміром, а також відчувайте комфорт у взаємодії з ними.
Що ви дізнаєтеся
- Як працює життєвий цикл активності.
- Коли активність починається, припиняється, зупиняється та знищується.
- Про методи зворотного виклику життєвого циклу, пов’язані зі змінами активності.
- Наслідки дій (наприклад, зміни конфігурації), які можуть призвести до подій життєвого циклу активності.
- Як зберегти стан активності протягом подій життєвого циклу.
Що ти зробиш
- Додайте код до програми TwoActivities із попередньої практики, щоб реалізувати різні зворотні виклики життєвого циклу Activity, щоб включити оператори журналювання.
- Спостерігайте за змінами стану під час роботи вашої програми та під час взаємодії з кожною діяльністю у вашій програмі.
- Змініть свою програму, щоб зберегти стан екземпляра активності, яка несподівано відтворюється у відповідь на поведінку користувача або зміну конфігурації на пристрої.
2. Огляд програми
У цій практиці ви додаєте до програми TwoActivities . Програма виглядає та поводиться приблизно так само, як і в останній кодовій роботі. Він містить дві реалізації Activity і дає користувачеві можливість надсилати між ними. Зміни, які ви вносите в програму під час цієї практики, не вплинуть на її видиму поведінку користувача.
3. 3. Завдання 1: Додайте зворотні виклики життєвого циклу до TwoActivities
У цьому завданні ви реалізуєте всі методи зворотного виклику життєвого циклу Activity для друку повідомлень у logcat, коли ці методи викликаються. Ці повідомлення журналу дозволять вам побачити, коли змінюється стан життєвого циклу активності та як ці зміни стану життєвого циклу впливають на вашу програму під час її роботи.
1.1 (Необов’язково) Скопіюйте проект TwoActivities
Для виконання завдань у цій практиці ви зміните існуючий проект TwoActivities , створений під час останньої практики. Якщо ви бажаєте зберегти попередній проект TwoActivities без змін, виконайте кроки в Додатку: Службові програми , щоб створити копію проекту.
1.2 Впровадити зворотні виклики в MainActivity
- Відкрийте проект TwoActivities в Android Studio та відкрийте MainActivity на панелі «Проект» > «Android».
- У метод onCreate() додайте такі оператори журналу:
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
- Додайте перевизначення для зворотного виклику onStart() із оператором у журнал для цієї події:
@Override
public void onStart(){
super.onStart();
Log.d(LOG_TAG, "onStart");
}
Для ярлика виберіть «Код» > «Замінити методи» в Android Studio. З’явиться діалогове вікно з усіма можливими методами, які ви можете змінити у своєму класі. Вибір одного або кількох методів зворотного виклику зі списку вставляє повний шаблон для цих методів, включаючи необхідний виклик суперкласу.
- Використовуйте метод onStart() як шаблон для реалізації зворотних викликів життєвого циклу onPause(), onRestart(), onResume(), onStop() і onDestroy().
Усі методи зворотного виклику мають однакові підписи (за винятком імені). Якщо ви копіюєте та вставляєте onStart(), щоб створити ці інші методи зворотного виклику, не забудьте оновити вміст, щоб викликати правильний метод у суперкласі та зареєструвати правильний метод.
- Запустіть свою програму.
- Натисніть вкладку Logcat внизу Android Studio, щоб відобразити панель Logcat. Ви повинні побачити три повідомлення журналу, що показують три стани життєвого циклу, через які дія перейшла під час її початку:
D/MainActivity: -------
D/MainActivity: onCreate
D/MainActivity: onStart
D/MainActivity: onResume
1.3 Впровадити зворотні виклики життєвого циклу в SecondActivity
Тепер, коли ви реалізували методи зворотного виклику життєвого циклу для MainActivity, зробіть те саме для SecondActivity.
- Відкрийте SecondActivity.
- У верхній частині класу додайте константу для змінної LOG_TAG:
private static final String LOG_TAG = SecondActivity.class.getSimpleName();
- Додайте зворотні виклики життєвого циклу та оператори журналу до другої дії. (Ви можете скопіювати та вставити методи зворотного виклику з MainActivity.)
- Додайте оператор журналу до методу returnReply() безпосередньо перед методом finish():
Log.d(LOG_TAG, "End SecondActivity");
1.4 Спостерігайте за журналом під час роботи програми**
- Запустіть свою програму.
- Натисніть вкладку Logcat внизу Android Studio, щоб відобразити панель Logcat.
- Введіть Діяльність у вікні пошуку. Android logcat може бути дуже довгим і захаращеним. Оскільки змінна LOG_TAG у кожному класі містить слова MainActivity або SecondActivity, це ключове слово дозволяє фільтрувати журнал лише за тим, що вас цікавить.
Експериментуйте зі своїм додатком і зверніть увагу на події життєвого циклу, які відбуваються у відповідь на різні дії. Зокрема, спробуйте такі речі:
- Використовуйте програму як зазвичай (надішліть повідомлення, дайте відповідь іншим повідомленням).
- Використовуйте кнопку «Назад», щоб повернутися від другої дії до основної.
- Використовуйте стрілку вгору на панелі програми, щоб повернутися від другої дії до основної.
- Обертайте пристрій як на основній, так і на другій активності в різний час у вашій програмі та спостерігайте, що відбувається в * журналі та на екрані.
- Натисніть кнопку огляду (квадратна кнопка праворуч від Home) і закрийте програму (торкніться X).
- Поверніться на головний екран і перезапустіть програму.
ПОРАДА. Якщо ви запускаєте свою програму в емуляторі, ви можете імітувати обертання за допомогою Control+F11 або Control+Function+F11.
Код розв’язку завдання 1
Наведені нижче фрагменти коду показують код рішення для першого завдання.
Основна діяльність
Наведені нижче фрагменти коду показують доданий код у MainActivity, але не весь клас.
Метод onCreate():
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Log the start of the onCreate() method.
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
// Initialize all the view variables.
mMessageEditText = findViewById(R.id.editText_main);
mReplyHeadTextView = findViewById(R.id.text_header_reply);
mReplyTextView = findViewById(R.id.text_message_reply);
}
Інші методи життєвого циклу:
@Override
protected void onStart() {
super.onStart();
Log.d(LOG_TAG, "onStart");
}
@Override
protected void onPause() {
super.onPause();
Log.d(LOG_TAG, "onPause");
}
@Override
protected void onRestart() {
super.onRestart();
Log.d(LOG_TAG, "onRestart");
}
@Override
protected void onResume() {
super.onResume();
Log.d(LOG_TAG, "onResume");
}
@Override
protected void onStop() {
super.onStop();
Log.d(LOG_TAG, "onStop");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(LOG_TAG, "onDestroy");
}
SecondActivity
Наступні фрагменти коду показують доданий код у SecondActivity, але не весь клас.
У верхній частині класу SecondActivity:
private static final String LOG_TAG = SecondActivity.class.getSimpleName();
Метод returnReply():
public void returnReply(View view) {
String reply = mReply.getText().toString();
Intent replyIntent = new Intent();
replyIntent.putExtra(EXTRA_REPLY, reply);
setResult(RESULT_OK, replyIntent);
Log.d(LOG_TAG, "End SecondActivity");
finish();
}
Інші методи життєвого циклу:
Те саме, що для MainActivity вище.
4. 4. Завдання 2: Збережіть та відновіть стан екземпляра Activity
Залежно від системних ресурсів і поведінки користувача кожна активність у вашій програмі може бути знищена та реконструйована набагато частіше, ніж ви думаєте.
Можливо, ви помітили цю поведінку в останньому розділі, коли обертали пристрій або емулятор. Обертання пристрою є одним із прикладів зміни конфігурації пристрою. Хоча ротація є найпоширенішою, усі зміни конфігурації призводять до знищення поточної активності та створення її заново, як якщо б вона була новою. Якщо ви не врахуєте таку поведінку у своєму коді, коли відбувається зміна конфігурації, ваш макет активності може повернутися до свого вигляду за замовчуванням і початкових значень, і ваші користувачі можуть втратити своє місце, дані або стан свого прогресу в ваш додаток.
Стан кожної активності зберігається як набір пар ключ/значення в об’єкті Bundle, що називається станом екземпляра активності. Система зберігає інформацію про стан за замовчуванням у пакеті стану екземпляра безпосередньо перед припиненням активності та передає цей пакет новому екземпляру активності для відновлення.
Щоб уникнути втрати даних у Activity, коли вони несподівано знищені та створені заново, вам потрібно реалізувати метод onSaveInstanceState(). Система викликає цей метод у вашій активності (між onPause() і onStop()), коли існує ймовірність, що дію може бути знищено та створено заново.
Дані, які ви зберігаєте в стані екземпляра, стосуються лише цього екземпляра цієї конкретної активності під час поточного сеансу програми. Коли ви зупиняєте та перезапускаєте новий сеанс програми, стан екземпляра Activity втрачається, і Activity повертається до свого вигляду за замовчуванням. Якщо вам потрібно зберігати дані користувача між сеансами програми, використовуйте спільні параметри або базу даних. Ви дізнаєтеся про обидва з них у наступному практичному занятті.
2.1 Збережіть стан екземпляра Activity за допомогою onSaveInstanceState()
Можливо, ви помітили, що обертання пристрою зовсім не впливає на стан другої активності. Це пов’язано з тим, що другий макет і стан активності генеруються з макета та наміру, який його активував. Навіть якщо Activity створено повторно, Intent все ще існує, і дані в цьому Intent все ще використовуються кожного разу, коли викликається метод onCreate() у другій Activity.
Крім того, ви можете помітити, що в кожній дії будь-який текст, який ви ввели в елементи повідомлення або відповіді EditText, зберігається навіть після повороту пристрою. Це пояснюється тим, що інформація про стан деяких елементів View у вашому макеті автоматично зберігається під час змін конфігурації, і поточне значення EditText є одним із таких випадків.
Тож єдиний стан Activity, який вас цікавить, — це елементи TextView для заголовка відповіді та текст відповіді в основній Activity. Обидва елементи TextView невидимі за замовчуванням; вони з’являються лише тоді, коли ви надсилаєте повідомлення назад до основної дії з другої дії.
У цьому завданні ви додаєте код для збереження стану екземпляра цих двох елементів TextView за допомогою onSaveInstanceState().
- Відкрийте MainActivity.
- Додайте цю скелетну реалізацію onSaveInstanceState() до дії або скористайтеся Кодом > Методи перевизначення, щоб вставити скелетну перевизначення.
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
- Перевірте, чи видимий заголовок наразі, і якщо так, помістіть цей стан видимості в пакет стану за допомогою методу putBoolean() і ключа «reply_visible».
if (mReplyHeadTextView.getVisibility() == View.VISIBLE) {
outState.putBoolean("reply_visible", true);
}
Пам’ятайте, що заголовок і текст відповіді позначено як невидимі, доки не буде відповіді від другої дії. Якщо заголовок видно, це означає, що є дані відповіді, які потрібно зберегти. Зауважте, що нас цікавить лише цей стан видимості — фактичний текст заголовка не потрібно зберігати, оскільки цей текст ніколи не змінюється.
- Усередині цієї самої перевірки додайте текст відповіді в пакет.
outState.putString("reply_text",mReplyTextView.getText().toString());
Якщо заголовок видно, ви можете припустити, що саме повідомлення відповіді також видно. Вам не потрібно перевіряти чи зберігати поточний стан видимості повідомлення-відповіді. Тільки фактичний текст повідомлення потрапляє в пакет стану з ключем "reply_text".
Ви зберігаєте стан лише тих елементів View, які можуть змінитися після створення Activity. Інші елементи View у вашій програмі (EditText, Button) можна будь-коли відтворити зі стандартного макета.
Зауважте, що система збереже стан деяких елементів View, наприклад вміст EditText.
2.2 Відновлення стану екземпляра Activity у onCreate()
Після того як ви зберегли стан екземпляра Activity, вам також потрібно відновити його під час повторного створення Activity. Ви можете зробити це або в onCreate(), або реалізувавши зворотний виклик onRestoreInstanceState(), який викликається після onStart() після створення Activity.
У більшості випадків найкращим місцем для відновлення стану активності є onCreate(), щоб гарантувати, що інтерфейс користувача, включно зі станом, стане доступним якомога швидше. Іноді зручно зробити це в onRestoreInstanceState() після завершення всієї ініціалізації або дозволити підкласам вирішити, чи використовувати вашу реалізацію за замовчуванням.
- У методі onCreate() після ініціалізації змінних View за допомогою findViewById() додайте перевірку, щоб переконатися, що savedInstanceState не дорівнює null.
// Initialize all the view variables.
mMessageEditText = findViewById(R.id.editText_main);
mReplyHeadTextView = findViewById(R.id.text_header_reply);
mReplyTextView = findViewById(R.id.text_message_reply);
// Restore the state.
if (savedInstanceState != null) {
}
Коли вашу дію створено, система передає пакет стану onCreate() як єдиний аргумент. Під час першого виклику onCreate() і запуску вашої програми Bundle стає нульовим — під час першого запуску вашої програми немає жодного стану. Подальші виклики onCreate() мають пакет, заповнений даними, які ви зберегли в onSaveInstanceState().
- Усередині цієї перевірки отримайте поточну видимість (true або false) із Bundle за допомогою ключа "reply_visible".
if (savedInstanceState != null) {
boolean isVisible =
savedInstanceState.getBoolean("reply_visible");
}
- Додайте перевірку під попереднім рядком для змінної isVisible.
if (isVisible) {
}
Якщо в пакеті стану є ключ reply_visible (і тому isVisible має значення true), вам потрібно буде відновити стан.
- Усередині тесту isVisible зробіть видимим заголовок.
mReplyHeadTextView.setVisibility(View.VISIBLE);
- Отримайте текстове повідомлення-відповідь із Bundle за допомогою ключа "reply_text" і налаштуйте TextView для відповіді, щоб показувати цей рядок.
mReplyTextView.setText(savedInstanceState.getString("reply_text"));
- Зробіть відповідь TextView також видимою:
mReplyTextView.setVisibility(View.VISIBLE);
- Запустіть програму. Спробуйте повернути пристрій або емулятор, щоб переконатися, що повідомлення відповіді (якщо воно є) залишається на екрані після повторного створення дії.
Код розв’язання завдання 2
Наведені нижче фрагменти коду показують код рішення для цього завдання.
Основна діяльність
Наведені нижче фрагменти коду показують доданий код у MainActivity, але не весь клас.
Метод onSaveInstanceState():
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// If the heading is visible, message needs to be saved.
// Otherwise we're still using default layout.
if (mReplyHeadTextView.getVisibility() == View.VISIBLE) {
outState.putBoolean("reply_visible", true);
outState.putString("reply_text",
mReplyTextView.getText().toString());
}
}
Метод onCreate():
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
// Initialize all the view variables.
mMessageEditText = findViewById(R.id.editText_main);
mReplyHeadTextView = findViewById(R.id.text_header_reply);
mReplyTextView = findViewById(R.id.text_message_reply);
// Restore the saved state.
// See onSaveInstanceState() for what gets saved.
if (savedInstanceState != null) {
boolean isVisible =
savedInstanceState.getBoolean("reply_visible");
// Show both the header and the message views. If isVisible is
// false or missing from the bundle, use the default layout.
if (isVisible) {
mReplyHeadTextView.setVisibility(View.VISIBLE);
mReplyTextView.setText(savedInstanceState
.getString("reply_text"));
mReplyTextView.setVisibility(View.VISIBLE);
}
}
}
Повний проект:
Проект Android Studio: TwoActivitiesLifecycle
5. Кодування
Завдання: створити просту програму зі списком покупок із основною діяльністю для списку, який створює користувач, і другою діяльністю для списку поширених товарів для покупок.
- Основна дія має містити список для створення, який має складатися з десяти порожніх елементів TextView.
- Кнопка «Додати товар» у основній дії запускає другу дію, яка містить список поширених товарів для покупок (сир, рис, яблука тощо). Використовуйте елементи Button для відображення елементів.
- Вибір елемента повертає користувача до основної дії та оновлює порожній TextView, щоб включити вибраний елемент.
Використовуйте намір для передачі інформації від однієї діяльності до іншої. Переконайтеся, що поточний стан списку покупок зберігається, коли користувач повертає пристрій.
6. Підведення підсумків
- Життєвий цикл активності — це набір станів, через які переміщується дія, починаючи з моменту її створення та закінчуючи, коли система Android відновлює ресурси для цієї дії.
- Коли користувач переходить від однієї дії до іншої, а також усередині та поза вашою програмою, кожна дія переходить між станами в життєвому циклі активності.
- Кожен стан у життєвому циклі Activity має відповідний метод зворотного виклику, який ви можете замінити у своєму класі Activity.
- Методами життєвого циклу є onCreate(), onStart(), onPause(), onRestart(), onResume(), onStop(), onDestroy().
- Заміна методу зворотного виклику життєвого циклу дозволяє вам додати поведінку, яка виникає, коли ваша діяльність переходить у цей стан.
- Ви можете додати скелетні методи заміни до своїх класів в Android Studio за допомогою «Код» > «Перевизначити».
- Зміни конфігурації пристрою, такі як обертання, призводять до того, що Activity знищується та створюється заново, ніби це було ново.
- Частина стану активності зберігається після зміни конфігурації, включаючи поточні значення елементів EditText. Для всіх інших даних ви повинні явно зберегти ці дані самостійно.
- Збережіть стан екземпляра Activity у методі onSaveInstanceState().
- Дані про стан екземпляра зберігаються як прості пари ключ/значення в наборі. Використовуйте методи Bundle, щоб додавати дані в Bundle і повертати дані з Bundle.
- Відновіть стан екземпляра за допомогою onCreate(), що є кращим способом, або onRestoreInstanceState(). Назад
1. Ласкаво просимо
Ця практична код-лабораторія є частиною Розділу 1: Початок роботи в курсі Основ розробника Android (версія 2). Ви отримаєте найбільшу користь від цього курсу, якщо будете працювати над кодовими лабораторіями в послідовності:
- Щоб отримати повний перелік кодових робіт у курсі, перегляньте Codelabs для Android Developer Fundamentals (V2).
- Докладні відомості про курс, включаючи посилання на всі концептуальні розділи, програми та слайди, див. в Основах розробника Android (версія 2).
вступ
У цій практиці ви дізнаєтеся більше про життєвий цикл діяльності. Життєвий цикл — це набір станів, у яких може перебувати активність протягом усього життєвого циклу, від моменту створення до моменту знищення, коли система повертає свої ресурси. Коли користувач переходить між діями у вашій програмі (а також у вашій програмі та з неї), дії переходять між різними станами у своєму життєвому циклі.
Кожен етап у життєвому циклі дії має відповідний метод зворотного виклику: onCreate(), onStart(), onPause() і так далі. Коли дія змінює стан, викликається відповідний метод зворотного виклику. Ви вже бачили один із цих методів: onCreate(). Замінивши будь-який із методів зворотного виклику життєвого циклу у ваших класах Activity, ви можете змінити поведінку активності за замовчуванням у відповідь на дії користувача чи системи.
Стан активності також може змінюватися у відповідь на зміни конфігурації пристрою, наприклад, коли користувач обертає пристрій із книжкової в альбомну. Коли відбуваються ці зміни конфігурації, діяльність знищується та відтворюється у стані за замовчуванням, і користувач може втратити інформацію, яку він ввів у дії. Щоб не заплутувати своїх користувачів, важливо розробити програму, щоб запобігти неочікуваній втраті даних. Далі в цій практичній програмі ви експериментуєте зі змінами конфігурації та дізнаєтесь, як зберегти стан активності у відповідь на зміни конфігурації пристрою та інші події життєвого циклу діяльності.
У цій практиці ви додаєте оператори журналювання до програми TwoActivities і спостерігаєте за змінами життєвого циклу діяльності під час використання програми. Потім ви починаєте працювати з цими змінами та досліджувати, як обробляти дані користувача за цих умов.
передумови
Ви повинні вміти:
- Створіть і запустіть проект програми в Android Studio .
- Додайте оператори журналу до своєї програми та переглядайте ці журнали на панелі Logcat.
- Розумійте та працюйте з Діяльністю та Наміром, а також відчувайте комфорт у взаємодії з ними.
Що ви дізнаєтеся
- Як працює життєвий цикл активності.
- Коли активність починається, припиняється, зупиняється та знищується.
- Про методи зворотного виклику життєвого циклу, пов’язані зі змінами активності.
- Наслідки дій (наприклад, зміни конфігурації), які можуть призвести до подій життєвого циклу активності.
- Як зберегти стан активності протягом подій життєвого циклу.
Що ти зробиш
- Додайте код до програми TwoActivities із попередньої практики, щоб реалізувати різні зворотні виклики життєвого циклу Activity, щоб включити оператори журналювання.
- Спостерігайте за змінами стану під час роботи вашої програми та під час взаємодії з кожною діяльністю у вашій програмі.
- Змініть свою програму, щоб зберегти стан екземпляра активності, яка несподівано відтворюється у відповідь на поведінку користувача або зміну конфігурації на пристрої.
2. Огляд програми
У цій практиці ви додаєте до програми TwoActivities . Програма виглядає та поводиться приблизно так само, як і в останній кодовій роботі. Він містить дві реалізації Activity і дає користувачеві можливість надсилати між ними. Зміни, які ви вносите в програму під час цієї практики, не вплинуть на її видиму поведінку користувача.
3. 3. Завдання 1: Додайте зворотні виклики життєвого циклу до TwoActivities
У цьому завданні ви реалізуєте всі методи зворотного виклику життєвого циклу Activity для друку повідомлень у logcat, коли ці методи викликаються. Ці повідомлення журналу дозволять вам побачити, коли змінюється стан життєвого циклу активності та як ці зміни стану життєвого циклу впливають на вашу програму під час її роботи.
1.1 (Необов’язково) Скопіюйте проект TwoActivities
Для виконання завдань у цій практиці ви зміните існуючий проект TwoActivities , створений під час останньої практики. Якщо ви бажаєте зберегти попередній проект TwoActivities без змін, виконайте кроки в Додатку: Службові програми , щоб створити копію проекту.
1.2 Впровадити зворотні виклики в MainActivity
- Відкрийте проект TwoActivities в Android Studio та відкрийте MainActivity на панелі «Проект» > «Android».
- У метод onCreate() додайте такі оператори журналу:
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
- Додайте перевизначення для зворотного виклику onStart() із оператором у журнал для цієї події:
@Override
public void onStart(){
super.onStart();
Log.d(LOG_TAG, "onStart");
}
Для ярлика виберіть «Код» > «Замінити методи» в Android Studio. З’явиться діалогове вікно з усіма можливими методами, які ви можете змінити у своєму класі. Вибір одного або кількох методів зворотного виклику зі списку вставляє повний шаблон для цих методів, включаючи необхідний виклик суперкласу.
- Використовуйте метод onStart() як шаблон для реалізації зворотних викликів життєвого циклу onPause(), onRestart(), onResume(), onStop() і onDestroy().
Усі методи зворотного виклику мають однакові підписи (за винятком імені). Якщо ви копіюєте та вставляєте onStart(), щоб створити ці інші методи зворотного виклику, не забудьте оновити вміст, щоб викликати правильний метод у суперкласі та зареєструвати правильний метод.
- Запустіть свою програму.
- Натисніть вкладку Logcat внизу Android Studio, щоб відобразити панель Logcat. Ви повинні побачити три повідомлення журналу, що показують три стани життєвого циклу, через які дія перейшла під час її початку:
D/MainActivity: -------
D/MainActivity: onCreate
D/MainActivity: onStart
D/MainActivity: onResume
1.3 Впровадити зворотні виклики життєвого циклу в SecondActivity
Тепер, коли ви реалізували методи зворотного виклику життєвого циклу для MainActivity, зробіть те саме для SecondActivity.
- Відкрийте SecondActivity.
- У верхній частині класу додайте константу для змінної LOG_TAG:
private static final String LOG_TAG = SecondActivity.class.getSimpleName();
- Додайте зворотні виклики життєвого циклу та оператори журналу до другої дії. (Ви можете скопіювати та вставити методи зворотного виклику з MainActivity.)
- Додайте оператор журналу до методу returnReply() безпосередньо перед методом finish():
Log.d(LOG_TAG, "End SecondActivity");
1.4 Спостерігайте за журналом під час роботи програми**
- Запустіть свою програму.
- Натисніть вкладку Logcat внизу Android Studio, щоб відобразити панель Logcat.
- Введіть Діяльність у вікні пошуку. Android logcat може бути дуже довгим і захаращеним. Оскільки змінна LOG_TAG у кожному класі містить слова MainActivity або SecondActivity, це ключове слово дозволяє фільтрувати журнал лише за тим, що вас цікавить.
Експериментуйте зі своїм додатком і зверніть увагу на події життєвого циклу, які відбуваються у відповідь на різні дії. Зокрема, спробуйте такі речі:
- Використовуйте програму як зазвичай (надішліть повідомлення, дайте відповідь іншим повідомленням).
- Використовуйте кнопку «Назад», щоб повернутися від другої дії до основної.
- Використовуйте стрілку вгору на панелі програми, щоб повернутися від другої дії до основної.
- Обертайте пристрій як на основній, так і на другій активності в різний час у вашій програмі та спостерігайте, що відбувається в * журналі та на екрані.
- Натисніть кнопку огляду (квадратна кнопка праворуч від Home) і закрийте програму (торкніться X).
- Поверніться на головний екран і перезапустіть програму.
ПОРАДА. Якщо ви запускаєте свою програму в емуляторі, ви можете імітувати обертання за допомогою Control+F11 або Control+Function+F11.
Код розв’язку завдання 1
Наведені нижче фрагменти коду показують код рішення для першого завдання.
Основна діяльність
Наведені нижче фрагменти коду показують доданий код у MainActivity, але не весь клас.
Метод onCreate():
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Log the start of the onCreate() method.
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
// Initialize all the view variables.
mMessageEditText = findViewById(R.id.editText_main);
mReplyHeadTextView = findViewById(R.id.text_header_reply);
mReplyTextView = findViewById(R.id.text_message_reply);
}
Інші методи життєвого циклу:
@Override
protected void onStart() {
super.onStart();
Log.d(LOG_TAG, "onStart");
}
@Override
protected void onPause() {
super.onPause();
Log.d(LOG_TAG, "onPause");
}
@Override
protected void onRestart() {
super.onRestart();
Log.d(LOG_TAG, "onRestart");
}
@Override
protected void onResume() {
super.onResume();
Log.d(LOG_TAG, "onResume");
}
@Override
protected void onStop() {
super.onStop();
Log.d(LOG_TAG, "onStop");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(LOG_TAG, "onDestroy");
}
SecondActivity
Наступні фрагменти коду показують доданий код у SecondActivity, але не весь клас.
У верхній частині класу SecondActivity:
private static final String LOG_TAG = SecondActivity.class.getSimpleName();
Метод returnReply():
public void returnReply(View view) {
String reply = mReply.getText().toString();
Intent replyIntent = new Intent();
replyIntent.putExtra(EXTRA_REPLY, reply);
setResult(RESULT_OK, replyIntent);
Log.d(LOG_TAG, "End SecondActivity");
finish();
}
Інші методи життєвого циклу:
Те саме, що для MainActivity вище.
4. 4. Завдання 2: Збережіть та відновіть стан екземпляра Activity
Залежно від системних ресурсів і поведінки користувача кожна активність у вашій програмі може бути знищена та реконструйована набагато частіше, ніж ви думаєте.
Можливо, ви помітили цю поведінку в останньому розділі, коли обертали пристрій або емулятор. Обертання пристрою є одним із прикладів зміни конфігурації пристрою. Хоча ротація є найпоширенішою, усі зміни конфігурації призводять до знищення поточної активності та створення її заново, як якщо б вона була новою. Якщо ви не врахуєте таку поведінку у своєму коді, коли відбувається зміна конфігурації, ваш макет активності може повернутися до свого вигляду за замовчуванням і початкових значень, і ваші користувачі можуть втратити своє місце, дані або стан свого прогресу в ваш додаток.
Стан кожної активності зберігається як набір пар ключ/значення в об’єкті Bundle, що називається станом екземпляра активності. Система зберігає інформацію про стан за замовчуванням у пакеті стану екземпляра безпосередньо перед припиненням активності та передає цей пакет новому екземпляру активності для відновлення.
Щоб уникнути втрати даних у Activity, коли вони несподівано знищені та створені заново, вам потрібно реалізувати метод onSaveInstanceState(). Система викликає цей метод у вашій активності (між onPause() і onStop()), коли існує ймовірність, що дію може бути знищено та створено заново.
Дані, які ви зберігаєте в стані екземпляра, стосуються лише цього екземпляра цієї конкретної активності під час поточного сеансу програми. Коли ви зупиняєте та перезапускаєте новий сеанс програми, стан екземпляра Activity втрачається, і Activity повертається до свого вигляду за замовчуванням. Якщо вам потрібно зберігати дані користувача між сеансами програми, використовуйте спільні параметри або базу даних. Ви дізнаєтеся про обидва з них у наступному практичному занятті.
2.1 Збережіть стан екземпляра Activity за допомогою onSaveInstanceState()
Можливо, ви помітили, що обертання пристрою зовсім не впливає на стан другої активності. Це пов’язано з тим, що другий макет і стан активності генеруються з макета та наміру, який його активував. Навіть якщо Activity створено повторно, Intent все ще існує, і дані в цьому Intent все ще використовуються кожного разу, коли викликається метод onCreate() у другій Activity.
Крім того, ви можете помітити, що в кожній дії будь-який текст, який ви ввели в елементи повідомлення або відповіді EditText, зберігається навіть після повороту пристрою. Це пояснюється тим, що інформація про стан деяких елементів View у вашому макеті автоматично зберігається під час змін конфігурації, і поточне значення EditText є одним із таких випадків.
Тож єдиний стан Activity, який вас цікавить, — це елементи TextView для заголовка відповіді та текст відповіді в основній Activity. Обидва елементи TextView невидимі за замовчуванням; вони з’являються лише тоді, коли ви надсилаєте повідомлення назад до основної дії з другої дії.
У цьому завданні ви додаєте код для збереження стану екземпляра цих двох елементів TextView за допомогою onSaveInstanceState().
- Відкрийте MainActivity.
- Додайте цю скелетну реалізацію onSaveInstanceState() до дії або скористайтеся Кодом > Методи перевизначення, щоб вставити скелетну перевизначення.
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
- Перевірте, чи видимий заголовок наразі, і якщо так, помістіть цей стан видимості в пакет стану за допомогою методу putBoolean() і ключа «reply_visible».
if (mReplyHeadTextView.getVisibility() == View.VISIBLE) {
outState.putBoolean("reply_visible", true);
}
Пам’ятайте, що заголовок і текст відповіді позначено як невидимі, доки не буде відповіді від другої дії. Якщо заголовок видно, це означає, що є дані відповіді, які потрібно зберегти. Зауважте, що нас цікавить лише цей стан видимості — фактичний текст заголовка не потрібно зберігати, оскільки цей текст ніколи не змінюється.
- Усередині цієї самої перевірки додайте текст відповіді в пакет.
outState.putString("reply_text",mReplyTextView.getText().toString());
Якщо заголовок видно, ви можете припустити, що саме повідомлення відповіді також видно. Вам не потрібно перевіряти чи зберігати поточний стан видимості повідомлення-відповіді. Тільки фактичний текст повідомлення потрапляє в пакет стану з ключем "reply_text".
Ви зберігаєте стан лише тих елементів View, які можуть змінитися після створення Activity. Інші елементи View у вашій програмі (EditText, Button) можна будь-коли відтворити зі стандартного макета.
Зауважте, що система збереже стан деяких елементів View, наприклад вміст EditText.
2.2 Відновлення стану екземпляра Activity у onCreate()
Після того як ви зберегли стан екземпляра Activity, вам також потрібно відновити його під час повторного створення Activity. Ви можете зробити це або в onCreate(), або реалізувавши зворотний виклик onRestoreInstanceState(), який викликається після onStart() після створення Activity.
У більшості випадків найкращим місцем для відновлення стану активності є onCreate(), щоб гарантувати, що інтерфейс користувача, включно зі станом, стане доступним якомога швидше. Іноді зручно зробити це в onRestoreInstanceState() після завершення всієї ініціалізації або дозволити підкласам вирішити, чи використовувати вашу реалізацію за замовчуванням.
- У методі onCreate() після ініціалізації змінних View за допомогою findViewById() додайте перевірку, щоб переконатися, що savedInstanceState не дорівнює null.
// Initialize all the view variables.
mMessageEditText = findViewById(R.id.editText_main);
mReplyHeadTextView = findViewById(R.id.text_header_reply);
mReplyTextView = findViewById(R.id.text_message_reply);
// Restore the state.
if (savedInstanceState != null) {
}
Коли вашу дію створено, система передає пакет стану onCreate() як єдиний аргумент. Під час першого виклику onCreate() і запуску вашої програми Bundle стає нульовим — під час першого запуску вашої програми немає жодного стану. Подальші виклики onCreate() мають пакет, заповнений даними, які ви зберегли в onSaveInstanceState().
- Усередині цієї перевірки отримайте поточну видимість (true або false) із Bundle за допомогою ключа "reply_visible".
if (savedInstanceState != null) {
boolean isVisible =
savedInstanceState.getBoolean("reply_visible");
}
- Додайте перевірку під попереднім рядком для змінної isVisible.
if (isVisible) {
}
Якщо в пакеті стану є ключ reply_visible (і тому isVisible має значення true), вам потрібно буде відновити стан.
- Усередині тесту isVisible зробіть видимим заголовок.
mReplyHeadTextView.setVisibility(View.VISIBLE);
- Отримайте текстове повідомлення-відповідь із Bundle за допомогою ключа "reply_text" і налаштуйте TextView для відповіді, щоб показувати цей рядок.
mReplyTextView.setText(savedInstanceState.getString("reply_text"));
- Зробіть відповідь TextView також видимою:
mReplyTextView.setVisibility(View.VISIBLE);
- Запустіть програму. Спробуйте повернути пристрій або емулятор, щоб переконатися, що повідомлення відповіді (якщо воно є) залишається на екрані після повторного створення дії.
Код розв’язання завдання 2
Наведені нижче фрагменти коду показують код рішення для цього завдання.
Основна діяльність
Наведені нижче фрагменти коду показують доданий код у MainActivity, але не весь клас.
Метод onSaveInstanceState():
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// If the heading is visible, message needs to be saved.
// Otherwise we're still using default layout.
if (mReplyHeadTextView.getVisibility() == View.VISIBLE) {
outState.putBoolean("reply_visible", true);
outState.putString("reply_text",
mReplyTextView.getText().toString());
}
}
Метод onCreate():
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
// Initialize all the view variables.
mMessageEditText = findViewById(R.id.editText_main);
mReplyHeadTextView = findViewById(R.id.text_header_reply);
mReplyTextView = findViewById(R.id.text_message_reply);
// Restore the saved state.
// See onSaveInstanceState() for what gets saved.
if (savedInstanceState != null) {
boolean isVisible =
savedInstanceState.getBoolean("reply_visible");
// Show both the header and the message views. If isVisible is
// false or missing from the bundle, use the default layout.
if (isVisible) {
mReplyHeadTextView.setVisibility(View.VISIBLE);
mReplyTextView.setText(savedInstanceState
.getString("reply_text"));
mReplyTextView.setVisibility(View.VISIBLE);
}
}
}
Повний проект:
Проект Android Studio: TwoActivitiesLifecycle
5. Кодування
Завдання: створити просту програму зі списком покупок із основною діяльністю для списку, який створює користувач, і другою діяльністю для списку поширених товарів для покупок.
- Основна дія має містити список для створення, який має складатися з десяти порожніх елементів TextView.
- Кнопка «Додати товар» у основній дії запускає другу дію, яка містить список поширених товарів для покупок (сир, рис, яблука тощо). Використовуйте елементи Button для відображення елементів.
- Вибір елемента повертає користувача до основної дії та оновлює порожній TextView, щоб включити вибраний елемент.
Використовуйте намір для передачі інформації від однієї діяльності до іншої. Переконайтеся, що поточний стан списку покупок зберігається, коли користувач повертає пристрій.
6. Підведення підсумків
- Життєвий цикл активності — це набір станів, через які переміщується дія, починаючи з моменту її створення та закінчуючи, коли система Android відновлює ресурси для цієї дії.
- Коли користувач переходить від однієї дії до іншої, а також усередині та поза вашою програмою, кожна дія переходить між станами в життєвому циклі активності.
- Кожен стан у життєвому циклі Activity має відповідний метод зворотного виклику, який ви можете замінити у своєму класі Activity.
- Методами життєвого циклу є onCreate(), onStart(), onPause(), onRestart(), onResume(), onStop(), onDestroy().
- Заміна методу зворотного виклику життєвого циклу дозволяє вам додати поведінку, яка виникає, коли ваша діяльність переходить у цей стан.
- Ви можете додати скелетні методи заміни до своїх класів в Android Studio за допомогою «Код» > «Перевизначити».
- Зміни конфігурації пристрою, такі як обертання, призводять до того, що Activity знищується та створюється заново, ніби це було ново.
- Частина стану активності зберігається після зміни конфігурації, включаючи поточні значення елементів EditText. Для всіх інших даних ви повинні явно зберегти ці дані самостійно.
- Збережіть стан екземпляра Activity у методі onSaveInstanceState().
- Дані про стан екземпляра зберігаються як прості пари ключ/значення в наборі. Використовуйте методи Bundle, щоб додавати дані в Bundle і повертати дані з Bundle.
- Відновіть стан екземпляра за допомогою onCreate(), що є кращим способом, або onRestoreInstanceState(). Назад