Android - onDestroy () вызывается после onCreate () - PullRequest
0 голосов
/ 20 марта 2019

У меня работает скринсейвер, небольшая анимация. Когда пользователь прикасается к экрану, он перемещается в мой MainActivity. Для этого я переопределяю метод "onUserInteraction ()". Если вы не знакомы, любое физическое прикосновение к экрану устройства или к его кнопкам вызывает этот метод.

Нажатие на экран каждый раз успешно переводит меня на основную деятельность. Однако, если я нажму кнопку «Назад» или «Громкость», я получу серию событий ниже.

  1. OnCreate ()
  2. onResume ()
  3. OnPause ()
  4. OnCreate ()
  5. onResume ()
  6. onWindowFocusChanged ()
  7. OnStop ()
  8. OnDestroy ()

В onCreate () и onResume () я устанавливаю логическое значение true. В onPause () и onDestroy () логическое значение имеет значение false. Итак, у меня есть серьезная проблема, когда onDestroy () вызывается последним. В то же время я могу установить, что мой логический параметр должен изменяться только во время onPause (), так как он вызывается каждый раз, когда я меняю экраны, но эта проблема все еще беспокоит меня.

В моем Logcat, перед вызовом onDestroy (), я вижу следующую строку:

[MainActivity] Surface release

MainActivity в моем манифесте:

<activity
    android:name=".MainActivity"
    android:screenOrientation="sensorLandscape" />

Я указал выше, когда читал (где-то), что изменение запрошенной ориентации внутри onCreate () может вызвать мою проблему. Тем не менее, я добавляю флаги:

protected void onCreate(Bundle savedInstanceState){
    getWindow.addFlags(WindowManager.LayaoutParams.FLAG_TURN_SCREEN_ON);
    getWindow.addFlags(WindowManager.LayaoutParams.FLAG_KEEP_SCREEN_ON);
    setContentView(R.layout.activity_main);

    // other code...
}

Что мне действительно смешно, так это то, что у меня нет проблем при вызове onDestroy (). Все кнопки работают правильно, пункты меню, таймеры, фоновые сервисы. Кроме того, что это «уничтожает» мою логическую логику и «уничтожает» то, что я оставил от своей гордости ... на самом деле ничто не влияет. Это ошибка?

Запуск Android Studio 3.3.2 с Gradle 4.10.1

Заранее спасибо за любую помощь.

РЕДАКТИРОВАТЬ (21 марта 2019 г.)

Чтобы ответить на вопрос логической логики: у меня есть всплывающие окна, которые появляются на экране, пока пользователь находится на главном экране приложения, которое называется «MainActivity». Я также отслеживаю активность экрана-заставки - всплывающий запрос переместит пользователя на домашний экран, а затем откроет всплывающее окно.

В MainActivity.java

onCreate()  - isHomeScreenActive = true;
onPause()   - isHomeScreenActive = false;
onResume()  - isHomeScreenActive = true;
onDestroy() - isHomeScreenActive = false; //Temporarily removed

Переход на ScreenSaver из MainActivity не является проблемой, но я добавил код на всякий случай.

   public void startScreenSaverTimer(){

       // Restarts the timer when method is called.
       // Touch events, onResume(), onCreate() call this
       if(timer != null){
           timer.cancel();
       }

       // Start Timer
       timer = new Timer();
       timer.schedule(new TimerTask(){
           @Override
           public void run(){
               finish();
               Intent ScreenSaver = new Intent(this, ScreenSaver.class);
               ScreenSaver.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
                                    Intent.FLAG_ACTIVITY_CLEAR_TOP);
               startActivity(ScreenSaver);
           }
       }, 60000); //Set to 1 minute
   }

По запросу я добавил «это» в свои журналы. Результаты ниже:

E/Tracker: onCreate() Boolean Value = true
E/Tracker: onCreate() called from com.x.x.MainActivity@be81228
E/Tracker: onResume() Boolean Value = true
E/Tracker: onResume() called from: com.x.x.MainActivity@be81228
E/Tracker: onPause() Boolean Value = false
E/Tracker: onPause() called from com.x.x.MainActivity@be81228
E/Tracker: onCreate() Boolean Value = true
E/Tracker: onCreate() called from com.x.x.MainActivity@d0faced
E/Tracker: onResume() Boolean Value = true
E/Tracker: onResume() called from: com.x.x.MainActivity@d0faced
E/Tracker: onWindowFocusChanged() called from com.x.x.MainActivity@d0faced
E/Tracker: onStop() called from com.x.x.MainActivity@be81228
E/Tracker: onDestroy() called from: com.x.x.MainActivity@be81228

Глядя на вышесказанное, похоже, что мы запускаем MainActivity дважды. Хороший звонок @ Дэвид Вассер. Похоже, мы на шаг ближе к решению этой проблемы.

MainActivity@be81228 (started first, gets Destroyed)
MainActivity@d0faced (started second, stays alive)

Поскольку похоже, что мы запускаем MainActivity дважды, я добавил код ScreenSaver, который запускает MainActivity.

@Override
public void onUserInteraction(){
    super.onUserInteraction();

    // Boolean for tracking screensaver
    isScreenSaverActive = false;

    if(animation != null){
        if(animation.isRunning(){
            animation.stop();
        }
    }

    finish();

    Intent i = new Intent(this, MainActivity.class);
    i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
               Intent.FLAG_ACTIVITY_CLEAR_TOP);
    startActivity(i)

    Log.e("Tracker", "ScreenSaver onUserInteraction() starting MainActivity);
}

Лог в вышеупомянутой функции, который я только что добавил, дает нам полезную подсказку:

E/Tracker: ScreenSaver onUserInteraction starting MainActivity
E/Tracker: ScreenSaver onUserInteraction starting MainActivity
E/Tracker: onCreate() Boolean Value = true
E/Tracker: onCreate() called from com.x.x.MainActivity@bcb1a2c
E/Tracker: onResume() Boolean Value = true
E/Tracker: onResume() called from: com.x.x.MainActivity@bcb1a2c
E/Tracker: onPause() Boolean Value = false
E/Tracker: onPause() called from com.x.x.MainActivity@bcb1a2c
E/Tracker: onCreate() Boolean Value = true
E/Tracker: onCreate() called from com.x.x.MainActivity@6ad37bf
E/Tracker: onResume() Boolean Value = true
E/Tracker: onResume() called from: com.x.x.MainActivity@6ad37bf
E/Tracker: onWindowFocusChanged() called from com.x.x.MainActivity@6ad37bf
E/Tracker: onStop() called from com.x.x.MainActivity@bcb1a2c
E/Tracker: onDestroy() called from: com.x.x.MainActivity@bcb1a2c

Похоже, onUserInteraction () дважды отвечает на KeyEvent. Возможно onKeyDown () и onKeyUp (). Поэтому, конечно, я тоже это записал:

E/Tracker: ScreenSaver onUserInteraction starting MainActivity
E/Tracker: ScreenSaver onKeyDown() BACK BUTTON
E/Tracker: ScreenSaver onUserInteraction starting MainActivity
E/Tracker: ScreenSaver onKeyUp() BACK BUTTON
// Same as above for the remainder of logs

Похоже, что KeyDown / KeyUp должны быть проблемой - для кнопки назад, кнопок громкости ... и, вероятно, для просмотра карты, bixby и кнопки home, которые я даже не думал проверять.

Пока что я сделал простой обходной путь, и он работает. Однако я чувствую, что должен быть более изящный подход. Любые идеи приветствуются.

private boolean runOnce = false;

@Override
public void onUserInteraction(){

    if(!runOnce){

       runOnce = true;
        // Start MainActivity

    }
}

Итак, я предполагаю, что мораль этой истории состоит в том, что запуск одного и того же действия дважды одновременно может вызвать вызов onDestroy () после создания действия "выжившего" клона. Единственная причина, по которой это было заметно для меня, заключалась в том, что мои обновления логических значений фактически обновляли статическую переменную в классе Singleton, используемом для управления всплывающими окнами в фоновых службах и некоторых других классах. В противном случае это, вероятно, осталось бы незамеченным.

РЕДАКТИРОВАТЬ (22 марта 2019 г.)

Манифест Android для MainActivity

    <activity
        android:name=".MainActivity"
        android:screenOrientation="sensorLandscape" />

Класс ScreenSaver, onUserInteraction ()

@Override
public void onUserInteraction(){
    super.onUserInteraction();

    if(!runOnce){

        runOnce = true;

        SingletonScreenSaverTracker.isScreenSaverActive = false;

        if(animation != null){

            if(animation.isRunning()){
                animation.stop();
            }

        }

        finish();

        Intent i = new Intent(this, MainActivity.class);
        i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK   |
                Intent.FLAG_ACTIVITY_CLEAR_TOP);

        startActivity(i);
    }
}

1 Ответ

0 голосов
/ 21 марта 2019

Использование функции onUserInteraction () может вызвать некоторые проблемы, если вы не будете осторожны.Нажатие кнопки фактически вызывает метод дважды, во время событий KeyDown и KeyUp.Если использовать этот метод для запуска упражнения, касание экрана будет работать нормально.Однако нажатие клавиши вызовет метод дважды, пытаясь запустить действие дважды, одновременно.

Когда два действия запускаются одновременно, Android распознает это и убивает одного из клонов.Как показали журналы, первый экземпляр стирается, но только после того, как второй экземпляр был полностью создан и имеет фокус окна.Таким образом, я смог увидеть, что onDestroy () вызывается в моей запущенной активности после onCreate ().

...