как реализовать onRetainNonConfigurationInstance

Я сделал медиаплеер в Android, он отлично работает, но когда я меняю ориентацию экрана, активность перезапускается. Я знаю, что этот вопрос уже задавался в stackoverflow несколько раз, но ни один из ответов мне не помог. я думаю, что я должен использовать: onRetainNonConfigurationInstance

    @Override 
public Object onRetainNonConfigurationInstance() { ... }

но я не знал, как правильно это реализовать, поэтому, если кто-то может дать мне учебник или неявный пример, я был бы признателен.


person AndroidM    schedule 11.06.2013    source источник


Ответы (3)


Я считаю, что onRetainNonConfigurationInstance() устарел. Вместо этого вам будет предложено использовать Fragments. Здесь находится ссылка на Fragment документацию. По сути, вы поместите свой пользовательский интерфейс и данные в пользовательский Fragment, а затем используйте FragmentManager для хранения экземпляра вашего Fragment. Затем, когда действие перезапустится, вы можете получить свой Fragment и изменить положение по мере необходимости.

person JorganPubshire    schedule 11.06.2013
comment
В настоящее время я использую отдельный поток для некоторых вещей, я могу представить, что фрагменты не помогут. - person basickarl; 31.10.2013
comment
И теперь фрагменты устарели. - person OdraEncoded; 13.07.2018
comment
Фрагменты не устарели. Только родные Фрагменты есть. Фрагменты поддержки не исчезнут в ближайшее время. - person swooby; 09.01.2019
comment
В документации предлагается использовать Fragment#setRetainInstance(boolean), который устарел на уровне API 28. - person Viktor Brešan; 09.12.2020

Неважно, что он устарел, он отлично работает. Проще всего было бы:

public Object onRetainNonConfigurationInstance() {
   return this;
}

Затем в YourActivity onCreate()

public void onCreate(Bundle savedState)
{
   YourActivity prevActivity = (YourActivity)getLastNonConfigurationInstance();
   if(prevActivity!= null) { 
       // So the orientation did change
       // Restore some field for example
       this.myValue = prevActivity.myValue;
   }
}
person Alexander Kulyakhtin    schedule 11.06.2013
comment
извините, это может быть глупый вопрос, но должен ли я поместить все атрибуты, которые я хочу сохранить, в onRetainNonConfigurationInstance() ?????? - person AndroidM; 11.06.2013
comment
Да, все, что вы хотите сохранить в виде одного объекта. Итак, когда вы возвращаете всю активность, вы получаете все обратно, но это, возможно, слишком много, возможно, вам нужно только одно или два поля, чтобы вы могли вернуть свой собственный объект MyState. Нет, никаких манифестных изменений не требуется. - person Alexander Kulyakhtin; 11.06.2013
comment
Но я сделал в ответ. Что не работает? Моя активность расширяет активность, без фрагментов. - person Alexander Kulyakhtin; 11.06.2013
comment
да, моя активность тоже расширяет активность, но я не получаю результата - person AndroidM; 11.06.2013
comment
На самом деле проще всего объявить переменную статической или элемент на статической карте. Тогда просто ожидайте, что это должно быть там. В конце концов, они исчезнут, когда активность будет окончательно уничтожена, но это тривиально и довольно постоянно (по крайней мере, на некоторых устройствах). - person Tatarize; 21.05.2015
comment
@Tatarize это неправильно, такая переменная не сохраняется при воссоздании активности - person Alexander Kulyakhtin; 21.05.2015
comment
@Alex Демонстративно, это так. Я сделал это для ограниченных целей, и да, он сохраняется в течение короткого времени. Фактически, он останется там до тех пор, пока активность не будет фактически уничтожена. По крайней мере, для Nexus 7. Я не знаю никаких гарантий, как долго он останется. Я бы не советовал, но попробовать можно. У меня есть. Оно работает. И этого вполне достаточно, чтобы растровое изображение выдержало поворот. - person Tatarize; 23.05.2015
comment
@Alex Хотя, очевидно, это следует считать плохой практикой. Пока сам класс не умрет, эта статика останется в памяти. И класс и загрузчик классов не выбрасываются из памяти до тех пор, пока процесс не будет убит, они сохраняются в памяти, пока класс загружается. Но даже в стеке пользовательского интерфейса он все еще использует эту память. Это сделает вашу программу более нуждающейся в смерти, так как ее приостановленное состояние занимает фактическую память, а не внутреннюю память/диск. Но он выживет до тех пор, пока ваша активность не будет уничтожена в каждой реализации, которую я видел. И ротация не разгружает классы. - person Tatarize; 23.05.2015

В своем медиаплеере, чтобы полностью не пересоздавать MediaPlayer, я сделал следующее:

1) В AndroidManifest.xml добавлен

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

2) Внутри MainActivity добавлено

 @Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    setSize(mVideoWidth, mVideoHeight);
}

Я надеюсь, что это помогает кому-то.

person Den    schedule 03.05.2018
comment
Теперь представьте, что у вас есть несколько ресурсов, зависящих от ориентации, каковы ваши планы, загружать их все вручную?! Нет, это не скользит. Вы можете реализовать это, если у вас мало ресурсов, зависящих от конфигурации. - person Farid; 24.08.2019