Остановка и перезапуск Activity
Правильная остановка и перезапуск вашей activity является важным процессом жизненного цикла activity , который дает пользователям чувство, что ваше приложение всегда живое и не теряет их прогресс. Есть несколько ключевых сценариев, в которых ваша activity останавливается и перезапускается:
- Пользователь открывает окно Недавние приложения и переключается с вашего приложения на другое приложение. activity вашего приложения, находящаяся в это время на переднем плане, останавливается. Если пользователь возвращается в ваше приложении с помощью значка запуска главного экрана или окна Недавние приложения, activity перезагружается.
- Пользователь выполняет действие в вашем приложении, которое начинается новую activity . Текущая activity будет остановлена, когда вторая activity будет создана. Если пользователь затем нажимает кнопку Назад , первая activity перезапустится.
- Пользователь получает телефонный звонок во время использования приложения на его или ее телефоне.
Activity класс предоставляет два метода жизненного цикла, onStop() и onRestart() , которые позволяют специально обрабатывать то, как ваша activity будет останавливаться и перезапускаться. В отличие от состояния приостановки, которое означает частичное перекрытие элементов пользовательского интерфейса, состояние остановки vгарантирует, что пользовательский интерфейс больше не виден и фокус пользователя находится в другой activity (или совершенно другом приложении).
Примечание: Поскольку система удерживает ваш Activity экземпляр в системной памяти, когда он остановлен, вполне возможно, что вам не нужно реализовывать onStop() и onRestart() (или даже onStart() методы вообще. Для большинства activity , которые относительно простые, activity будет остановлена и перезапущена вполне нормально, и вы, возможно, должны использовать только onPause() для приостановки текущих действий и отсоединения от системных ресурсов.
Рисунок 1. Когда пользователь покидает вашу activity , система вызывает onStop() для прекращения activity (1). Если пользователь возвращается по время остановки activity , система вызывает onRestart() (2), а затем быстро onStart() (3) и onResume() (4). Обратите внимание, что независимо от того, какой сценарий вызывает остановку activity , система всегда вызывает onPause() перед вызовом onStop() .
Остановка вашей activity
Когда ваша activity получает вызов onStop() метода, уже ничего не видно и вы должны освободить почти все ресурсы, которые не нужны, пока пользователь их не использует. После того, как ваша activity прекращается, система может уничтожить экземпляр, если это необходимо для восстановления системной памяти. В крайних случаях, система может просто убить ваш процесс приложения без вызова финального onDestroy() метода обратного вызова, поэтому очень важно использовать onStop() для освобождения ресурсов, которые могли бы привести к утечке памяти.
Несмотря на то, что onPause() метод вызывается до onStop() , вы должны использовать onStop() для выполнения более крупных и ресурсоемких операций завершения, таких как запись информации в базу данных.
Например, вот реализация onStop() , который сохраняет содержимое черновика записки в постоянное хранилище:
@Override protected void onStop() < super.onStop(); // Always call the superclass method first // Save the note's current draft, because the activity is stopping // and we want to be sure the current note progress isn't lost. ContentValues values = new ContentValues(); values.put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText()); values.put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle()); getContentResolver().update( mUri, // The URI for the note to update. values, // The map of column names and new values to apply to them. null, // No SELECT criteria are used. null // No WHERE columns are used. ); >
Когда ваша activity остановлена, Activity объект остается в оперативной памяти, и снова используется, когда activity возобновляет работу. Вам не нужно повторно инициализировать компоненты, которые были созданы в любом из методов обратного вызова, ведущего к Resumed состоянию. Система также отслеживает текущее состояние для каждого View в макете, так что если пользователь ввел текст в EditText виджет, то это содержание сохраняется, поэтому вам не нужно сохранять и восстанавливать его.
Примечание: Даже если система разрушает вашу activity , когда она остановлена, она все еще сохраняет состояние View объектов (например, текста в EditText ) в Bundle (в блобе с парами ключ-значение), и восстанавливает их, если пользователь переходит обратно в тот же экземпляр activity ( cледующий урок рассказывает больше об использовании Bundle для сохранения других данных состояния в случае, если ваша activity уничтожена и создана заново).
Запуск/перезапуск вашей activity
Когда ваша activity возвращается на первый план из остановленного состояния, она получает вызов onRestart() . Система также вызывает onStart() метод, который происходит каждый раз, когда ваша activity становится видимой пользователю (будь то перезапуск или объект создан впервые). onRestart() метод, однако, вызывается только когда activity возобновляется из остановленного состояния, так что вы можете использовать его для выполнения специальных реставрационных работ, которые могут быть необходимы, только если activity была ранее остановлена, но не уничтожена.
Это редкость, когда приложение должно использовать onRestart() для восстановления состояния activity , так что нет никаких руководящих принципов для этого метода, которые применялись бы для большинства приложений. Тем не менее, т.к. ваш onStop() метод должен был существенно очистить все ресурсы вашей activity , вы должны будете повторно создать их, когда vбудет перезагружаться. Тем не менее, вы также должны создать экземпляры ресурсов, когда ваша деятельность создается впервые (когда нет существующего экземпляра деятельности). По этой причине, вы должны, как правило, использовать onStart() метод обратного вызова как дополнение к onStop() метод, потому что система вызывает onStart() как при создании вашей activity , так и при перезапуске activity из остановленного состояния.
Например, т.к. пользователь, возможно, был далеко от вашего приложения в течение длительного времени прежде чем вернуться к нему, onStart() метод является хорошим местом, чтобы убедиться, что необходимые функции системы включены:
@Override protected void onStart() < super.onStart(); // Always call the superclass method first // The activity is either being restarted or started for the first time // so this is where we should make sure that GPS is enabled LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); if (!gpsEnabled) < // Create a dialog here that requests the user to enable GPS, and use an intent // with the android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS action // to take the user to the Settings screen to enable GPS when they click "OK" >> @Override protected void onRestart() < super.onRestart(); // Always call the superclass method first // Activity being restarted from stopped state >
Когда система разрушает вашу activity , она вызывает onDestroy() метод для вашей Activity . Т.к. вы должны, как правило, освободить большинство ваших ресурсов в onStop() , к тому времени, когда вы получаете вызов onDestroy() , не так много того, что большинство приложений должно сделать. Этот метод это ваш последний шанс вычистить ресурсы, которые могли бы привести к утечке памяти, так что вы должны быть уверены, что дополнительные потоки будут уничтожены, и другие долго работающие действия, такие как трассировка методов также остановились.
Продолжение: Повторное создание activity
Если не указано иное, этот контент распространяется под лицензией Creative Commons Attribution 2.5. Для получения дополнительной информации и ограничений, см. Лицензия контента.
How do I programmatically “restart” an Android app?
There are some situations, we need to restart whole application programmatically. This example demonstrates how do I programmatically “restart” an Android app.
Step 1 − Create a new project in Android Studio, go to File ⇒ New Project and fill all required details to create a new project.
Step 2 − Add the following code to res/layout/activity_main.xml.
In the above code, we have taken a text view. When the user clicks on text view, it will restart the whole application.
package com.example.andy.myapplication; import android.app.AlarmManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.os.Build; import android.os.Bundle; import android.support.annotation.RequiresApi; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.TextView; public class MainActivity extends AppCompatActivity < int view = R.layout.activity_main; TextView textview; @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN) @Override protected void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(view); textview = findViewById(R.id.text); textview.setText("Click here to restart activity"); textview.setOnClickListener(new View.OnClickListener() < @Override public void onClick(View v) < Intent mStartActivity = new Intent(MainActivity.this, MainActivity.class); int mPendingIntentId = 123456; PendingIntent mPendingIntent = PendingIntent.getActivity(MainActivity.this, mPendingIntentId, mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT); AlarmManager mgr = (AlarmManager)MainActivity.this.getSystemService(Context.ALARM_SERVICE); mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent); System.exit(0); >>); > >
In the above code, we have taken text view, when a user clicks on text view, it will restart the whole application as shown below —
Intent mStartActivity = new Intent(MainActivity.this, MainActivity.class); int mPendingIntentId = 123456; PendingIntent mPendingIntent = PendingIntent.getActivity(MainActivity.this, mPendingIntentId, mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT); AlarmManager mgr = (AlarmManager)MainActivity.this.getSystemService(Context.ALARM_SERVICE); mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent); System.exit(0);
Let’s try to run your application. I assume you have connected your actual Android Mobile device with your computer. To run the app from android studio, open one of your project’s activity files and click Run icon from the toolbar. Select your mobile device as an option and then check your mobile device which will display your default screen −
When you click on text view, it will restart application again after some time.
Click here to download the project code
Как программно «перезапустить» приложение для Android?
Во-первых, я знаю, что на самом деле нельзя убивать/перезапускать приложение на Android. В моем случае я хочу factory — reset мое приложение в конкретном случае, когда сервер отправляет клиенту определенную информацию. Пользователь может быть зарегистрирован на сервере только с ОДНОМ экземпляром приложения (т.е. несколько устройств не разрешены). Если другой экземпляр получает этот «logged-in» -lock, все остальные экземпляры этого пользователя должны удалить свои данные (factory — reset), чтобы поддерживать согласованность. Можно принудительно получить блокировку, поскольку пользователь может удалить приложение и переустановить его, что приведет к другому идентификатору экземпляра, и пользователь больше не сможет освободить блокировку. Поэтому можно принудительно получить блокировку. Из-за этой силовой возможности нам нужно всегда проверять конкретный пример, что он имеет блокировку. Это делается на (почти) каждом запросе на сервер. Сервер может послать «неверный-lock-id». Если это обнаружено, клиентское приложение должно удалить все. Это был прецедент. Нет для вопроса реализации: У меня есть Activity A, который запускает Login Activity L или главное приложение Activity B в зависимости от поля sharedPrefs. После запуска L или B он закрывается, так что работает только L или B. Таким образом, в том случае, если пользователь уже зарегистрирован в B, выполняется сейчас. B запускает C. C вызывает startService для IntentService D. Это приводит к этому стеку: (A) > B > C > D Из метода onHandleIntent D событие отправляется на ResultReceiver R. R теперь обрабатывает это событие, предоставляя пользователю диалог, в котором он может выбрать factory — reset приложение (удалить базу данных, sharedPrefs и т.д.). После factory — reset я хочу перезапустить приложение (чтобы закрыть все действия) и снова запустить A, который затем запускает login Activity L и заканчивается: (A) > L Метод Dialog onClick выглядит следующим образом:
@Override public void onClick(DialogInterface dialog, int which) < // Will call onCancelListener MyApplication.factoryReset(); // (Deletes the database, clears sharedPrefs, etc.) Intent i = new Intent(MyApp.getContext(), A.class); i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); MyApp.getContext().startActivity(i); >
public class MyApp extends Application < private static Context context; @Override public void onCreate() < super.onCreate(); context = getApplicationContext(); >public static Context getContext() < return context; >public static void factoryReset() < // . >>
Теперь проблема заключается в том, что если я использую FLAG_ACTIVITY_NEW_TASK , действия B и C все еще работают. Если я нажму кнопку «Назад» в login Activity , я вижу C, но я хочу вернуться на главный экран. Если я не устанавливаю FLAG_ACTIVITY_NEW_TASK , я получаю ошибку:
07-07 12:27:12.272: ERROR/AndroidRuntime(9512): android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
Я не могу использовать «Действия» Context , потому что ServiceIntent D также может быть вызван из фоновой задачи, которая запускается AlarmManager . Итак, как я могу решить это, чтобы стек активности стал (A) > L?