2013-04-10 1 views
18

Я видел несколько подобных вопросов о onSaveInstanceState не вызывался для Fragment с, но в моем случае Fragment сек работают нормально, это главный FragmentActivity, который возникли проблемы.FragmentActivity onSaveInstanceState не вызывался

Соответствующий код выглядит довольно просто:

public class MyFActivity extends FragmentActivity implements ActionBar.TabListener { 
    String[] allValues; // data to save 

    @Override 
    protected void onSaveInstanceState (Bundle outState) { 
     Log.d("putting it!", allValues.toString()); 
     outState.putStringArray("allValues", allValues); 
     super.onSaveInstanceState(outState); 
    } 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     if (savedInstanceState != null) { 
      allValues = savedInstanceState.getStringArray("allValues"); 
      Log.d("getting it!", allValues.toString()); 
     } 
    } 
} 

При приостановке деятельности (с помощью кнопки назад), то onSaveInstanceState никогда не вызывается, и, следовательно, savedInstanceState всегда null в методе onCreate при возобновлении приложения , Я попытался добавить блок, как это:

@Override 
public void onPause() { 
    super.onPause(); 
    onSaveInstanceState(new Bundle());  
} 

, который был предложен в https://stackoverflow.com/a/14195202/362657, но в то время как onSaveInstanceState затем получает называется, savedInstanceState остается null в onCreate метода. Что мне не хватает?

+3

«При приостановке действия (с помощью кнопки« назад ») обычно это разрушает фрагмент, поэтому« savedInstanceState »теряется. Вы видите соответствующее 'saveInstanceState' в' onCreate() 'при повороте устройства? – Sam

+0

Вместо onCreate, возможно, вы должны использовать onResume()? Если действие приостановлено, то onCreate() не следует снова вызывать, onResume() должен – Tom

+0

Хм, это объясняет! Уничтожено это. – SaltyNuts

ответ

77

Проблема в том, что вы не понимаете, как работает onSaveInstanceState. Он предназначен для сохранения состояния Activity/Fragment в случае, если ОС необходимо уничтожить его по соображениям памяти или изменениям конфигурации. Это состояние затем возвращается обратно в onCreate, когда Activity/Fragment возвращается в/перезапущен.

В Fragment все их обратные вызовы по жизненному циклу напрямую привязаны к их родителям Activity. Таким образом, onSaveInstanceState вызывается на Fragment, когда его родитель Activity имеет onSaveInstanceState.

При приостановке деятельности (с помощью кнопки назад), то onSaveInstanceState никогда не вызывается, и, следовательно, savedInstanceState всегда нуль в OnCreate метода при возобновлении приложения.

При нажатии назад, пользователь разрушает Activity, и поэтому его дети Fragment с, так что нет никаких оснований называть onSaveInstanceState, так как экземпляр уничтожается. Когда вы снова открываете Activity, это совершенно новый экземпляр без сохранения состояния, поэтому Bundle прошел в onCreate: null. Это ведет себя точно так же, как и предусмотрено. Однако попробуйте повернуть устройство или нажать кнопку «домой», после чего вы увидите Activity, а его дети Fragment s имеют onSaveInstanceState, а затем возвращены в onCreate при возврате.

хак вы добавили, непосредственно вызывая onSaveInstanceState(new Bundle()); внутри , это очень плохая практика, так как вы должны никогда вызов в течение жизненного цикла обратного вызова непосредственно. Это может привести ваше приложение к незаконным состояниям.

Если вы действительно хотите, чтобы ваши данные сохранялись за пределами вашего приложения, я предлагаю вам использовать SharedPreferences или databases для получения более сложных данных. Затем вы можете сохранить свои постоянные данные в onPause() или при каждом изменении.

Надеюсь, это поможет.

+0

Благодарим вас за подробное объяснение. У меня было ошибочное впечатление, что кнопка «Назад» помещает деятельность в фоновом режиме, не разрушая ее. – SaltyNuts

+0

Вы очень приветствуете, это сложная концепция, и она не документирована так хорошо, как хотелось бы. –

+0

@dymmeh это здорово, +1 к вам сэр –

7

В обновлении к принятому ответу:

осколком onSaveInstanceState может быть вызван, если вы используете ViewPager с FragmentStatePagerAdapter (а не FragmentPagerAdapter)

FragmentStatePagerAdapter в

Этот версия пейджера более полезна, когда имеется большое количество страниц, больше похоже на просмотр списка. Когда страницы не видны пользователю, их весь фрагмент может быть уничтожен, сохраняя сохраненное состояние этого фрагмента. Это позволяет пейджеру удерживать гораздо меньшую память, связанную с каждой посещенной страницей, по сравнению с FragmentPagerAdapter за счет потенциально большего количества накладных расходов при переключении между страницами.

И не забывайте:

При использовании FragmentPagerAdapter хост ViewPager должен иметь действительный набор ID.

+0

вы спасли мою жизнь: D –

Смежные вопросы