Подтвердить что ты не робот

Является ли действие уничтоженным, потому что ориентация изменилась или приложение закрывается?

У меня есть Activity, который запускает AsyncTask. Активность разрешена для отображения в портретной или альбомной ориентации. Когда ориентация изменяется, активность уничтожается и воссоздается. Задача продолжает работать независимо от того, сколько раз меняется ориентация. Он также возвращает результаты успешной деятельности (в соответствии с ответом CommonsWare здесь http://goo.gl/WF1yW).

Я хочу достичь: когда действие уничтожается, потому что приложение закрывается - задача должна быть отменена. Однако, когда действие уничтожается из-за изменения ориентации, задача не должна отменяться.

В основном вопрос заключается в том, как различать два случая: приложение закрывает/меняет ориентацию. В обоих случаях вызывается метод onDestroy() и нет простого способа проверить что-то вроде isChangingOrientation()...

P.S. Я также могу рассмотреть совершенно другой подход, если это необходимо.

4b9b3361

Ответ 1

В общем, вы не хотите определять onConfigurationChanged(), потому что так сложно все исправить. Наилучший подход заключается в том, чтобы приложение было убито и воссоздано при изменении ориентации.

Чтобы упростить переход, вы можете реализовать onRetainNonConfigurationInstance(). Этот метод будет вызываться системой, когда он узнает, что ваше приложение будет перезапущено почти сразу. В onRetainNonConfigurationInstance() вы передаете любой произвольный объект обратно в систему ('this' является разумным выбором). Затем в вашем методе onCreate() вы вызываете getLastNonConfigurationInstance() для получения ранее сохраненного объекта. Это позволяет очень быстро и легко восстановить состояние из предыдущего вызова. Я считаю, что даже запущенные потоки и открытые сокеты могут быть переданы через этот путь.

Подробнее см. Сохранить кеш при вращении устройства.

Ответ 2

вы можете использовать метод isFinishing(), чтобы проверить, будет ли активность убита или только что вызванный метод onDestroy() из-за изменения ориентации

@Override
protected void onDestroy() {
    super.onDestroy();
    if(isFinishing()){
        Log.i("DEBUG", "App will Terminate ");
    }else{
        Log.i("DEBUG", "Orientation changed");
    }

}

Ответ 3

Я нашел несколько удовлетворительное решение, которое хочу поделиться.

Метод onRetainNonConfigurationInstance() вызывается только при восстановлении Activity. Более конкретно: Called by the system, as part of destroying an activity due to a configuration change, when it is known that a new instance will immediately be created for the new configuration.

Я переопределяю этот метод и сохраняю флаг (указывающий, был ли он вызван или нет). Затем в onDestroy (который называется short after after) я проверяю этот флаг, и если он false, я отменяю фоновое задание, потому что активность уничтожается навсегда. Если он истина, это означает, что вызывается onRetainNonConfigurationInstance(), что означает, что активность воссоздана, поэтому я оставляю задачу запущенной.

Мне понравилось бы лучшее решение, но такого не найти. Проблемы с этим решением - два: метод устарел; существует без гарантии, что метод будет вызван (согласно документации). На практике решение работает для меня, поэтому я буду использовать его...

Ответ 4

Посмотрите здесь, чтобы лучше понять жизненный цикл Android: http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle

Вы можете использовать onConfigurationChanged() для обнаружения изменений ориентации в своей деятельности. Вы можете использовать метод onDestroy(), чтобы определить, когда ваша активность будет убита.

Ответ 5

Лучший способ, который я нашел после некоторого исследования, - создать класс приложения и полагаться на метод onTrimMemory(). Проблема с этим подходом - onTrimMemory() не вызывается, если время ожидания экрана или экран блокируется нажатием кнопки питания, поэтому мне пришлось реализовать эту логику отдельно.

/**
 * When your app process resides in the background LRU list:
 * TRIM_MEMORY_BACKGROUND
 * TRIM_MEMORY_MODERATE
 * TRIM_MEMORY_COMPLETE
 *
 * When your app visibility changes:
 * TRIM_MEMORY_UI_HIDDEN
 */
@Override
public void onTrimMemory(final int level) {
    super.onTrimMemory(level);
    if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
            || level == ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
            || level == ComponentCallbacks2.TRIM_MEMORY_COMPLETE
            || level == ComponentCallbacks2.TRIM_MEMORY_MODERATE) {

        // App went in background

    }
}

Следующий код предназначен для обнаружения блокировки экрана. Я реализовал этот код в одном из методов ActivityLifecycleCallbacks - onActivityStopped()

final PowerManager powerManager = (PowerManager) getAppContext().getSystemService(Context.POWER_SERVICE);
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
    if (!powerManager.isScreenOn()) {
        // Screen locked
    }
} else {
    if (!powerManager.isInteractive()) {
        // Screen locked    
    }
}

Ответ 6

Если ваше приложение нацелено на уровень API 13 или выше, вы должны установить эту конфигурацию в файле manifest.xml

<activity
android:configChanges="orientation|screenSize"
...
/>