【已解决】Android中getActivity().recreate()时出错:java.lang.IllegalStateException: setSelectedNavigationIndex not valid for current navigation mode

【背景】

之前折腾了:

【基本解决】Android中PreferenceFragment界面透明导致界面很混乱

但是接着又遇到其他方面的问题:

04-24 15:38:13.553: W/dalvikvm(3423): threadid=1: thread exiting with uncaught exception (group=0xb2f44288)
04-24 15:38:13.553: E/AndroidRuntime(3423): FATAL EXCEPTION: main
04-24 15:38:13.553: E/AndroidRuntime(3423): java.lang.RuntimeException: Unable to start activity ComponentInfo{xxx.yyy.zzz/xxx.yyy.zzz.aa.MainActivity}: java.lang.IllegalStateException: setSelectedNavigationIndex not valid for current navigation mode
04-24 15:38:13.553: E/AndroidRuntime(3423): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059)
04-24 15:38:13.553: E/AndroidRuntime(3423): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
04-24 15:38:13.553: E/AndroidRuntime(3423): at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3512)
04-24 15:38:13.553: E/AndroidRuntime(3423): at android.app.ActivityThread.access$700(ActivityThread.java:130)
04-24 15:38:13.553: E/AndroidRuntime(3423): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1201)
04-24 15:38:13.553: E/AndroidRuntime(3423): at android.os.Handler.dispatchMessage(Handler.java:99)
04-24 15:38:13.553: E/AndroidRuntime(3423): at android.os.Looper.loop(Looper.java:137)
04-24 15:38:13.553: E/AndroidRuntime(3423): at android.app.ActivityThread.main(ActivityThread.java:4745)
04-24 15:38:13.553: E/AndroidRuntime(3423): at java.lang.reflect.Method.invokeNative(Native Method)
04-24 15:38:13.553: E/AndroidRuntime(3423): at java.lang.reflect.Method.invoke(Method.java:511)
04-24 15:38:13.553: E/AndroidRuntime(3423): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
04-24 15:38:13.553: E/AndroidRuntime(3423): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
04-24 15:38:13.553: E/AndroidRuntime(3423): at dalvik.system.NativeStart.main(Native Method)
04-24 15:38:13.553: E/AndroidRuntime(3423): Caused by: java.lang.IllegalStateException: setSelectedNavigationIndex not valid for current navigation mode
04-24 15:38:13.553: E/AndroidRuntime(3423): at com.android.internal.app.ActionBarImpl.setSelectedNavigationItem(ActionBarImpl.java:362)
04-24 15:38:13.553: E/AndroidRuntime(3423): at xxx.yyy.zzz.aa.MainActivity.onRestoreInstanceState(MainActivity.java:654)
04-24 15:38:13.553: E/AndroidRuntime(3423): at android.app.Activity.performRestoreInstanceState(Activity.java:900)
04-24 15:38:13.553: E/AndroidRuntime(3423): at android.app.Instrumentation.callActivityOnRestoreInstanceState(Instrumentation.java:1130)
04-24 15:38:13.553: E/AndroidRuntime(3423): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2037)
04-24 15:38:13.553: E/AndroidRuntime(3423): ... 12 more

如图:

java.lang.IllegalStateException setSelectedNavigationIndex not valid for current navigation mode

对应代码是:

public class SettingFragment extends PreferenceFragment {
 @Override
 public void onCreate(Bundle savedInstanceState) {
//	 setTheme(R.style.AppBaseTheme);
  super.onCreate(savedInstanceState);
        // Load the preferences from an XML resource
        addPreferencesFromResource(R.xml.preferences);
......
  ......
  switchLanguage.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
     @Override
     public boolean onPreferenceChange(Preference preference,
       Object newValue) {
      ......
      res.updateConfiguration(config, res.getDisplayMetrics());
      SettingFragment.this.getActivity().recreate();
      return true;
     }
    });
 }
......
}

看起来是由于:

SettingFragment.this.getActivity().recreate();

而导致挂掉的。 

【解决过程】

1.然后重新调试期间,发现:

SettingFragment.this.getActivity()

得到的就是MainActivity,而接着出错,显示的是:

java.lang.IllegalStateException: setSelectedNavigationIndex not valid for current navigation mode

看了就是对于MainActivity来说的了。

2.继续调试,发现好像是在:

 @Override
 public void onRestoreInstanceState(Bundle savedInstanceState) {
  // Restore the previously serialized current tab position.
  if (savedInstanceState.containsKey(STATE_SELECTED_NAVIGATION_ITEM)) {
   getActionBar().setSelectedNavigationItem(
     savedInstanceState.getInt(STATE_SELECTED_NAVIGATION_ITEM));
  }
 }

挂掉的。

所以暂时注释掉:

 @Override
 public void onRestoreInstanceState(Bundle savedInstanceState) {
//	 // Restore the previously serialized current tab position.
//	 if (savedInstanceState.containsKey(STATE_SELECTED_NAVIGATION_ITEM)) {
//	 getActionBar().setSelectedNavigationItem(
//	 savedInstanceState.getInt(STATE_SELECTED_NAVIGATION_ITEM));
//	 }
 }

然后看看结果:

结果又发现,会先执行:

 @Override
 public void onSaveInstanceState(Bundle outState) {
  // Serialize the current tab position.
  outState.putInt(STATE_SELECTED_NAVIGATION_ITEM, getActionBar()
    .getSelectedNavigationIndex());
 }

然后才是onRestoreInstanceState。

3.然后去改为:

 @Override
 public void onSaveInstanceState(Bundle outState) {
  // Serialize the current tab position.
  //outState.putInt(STATE_SELECTED_NAVIGATION_ITEM, getActionBar().getSelectedNavigationIndex());
  if(null != mTabHost){
   outState.putInt(STATE_SELECTED_NAVIGATION_ITEM, mTabHost.getCurrentTab());
  }
 
 }
 @Override
 public void onRestoreInstanceState(Bundle savedInstanceState) {
  // Restore the previously serialized current tab position.
  if (savedInstanceState.containsKey(STATE_SELECTED_NAVIGATION_ITEM)) {
   //getActionBar().setSelectedNavigationItem(savedInstanceState.getInt(STATE_SELECTED_NAVIGATION_ITEM));
   if(null != mTabHost){
    mTabHost.setCurrentTab(savedInstanceState.getInt(STATE_SELECTED_NAVIGATION_ITEM));
   }
  }
 }

看看效果:

基本是解决了crash的问题。

不过对于tab的index还是没法保存。

4.最后改为:

public class MainActivity extends Activity implements ISubscriber{
    private static final String STATE_SELECTED_TAB_INDEX = "selected_tab_index";
   
    private int mPreSelectedTabIdx = 0;
   
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_main);
     
     mPreSelectedTabIdx = restoreSavedSelectedTabIdx(savedInstanceState);
    }
 @Override
 public void onSaveInstanceState(Bundle outState) {
  // Serialize the current tab position.
  //outState.putInt(STATE_SELECTED_NAVIGATION_ITEM, getActionBar().getSelectedNavigationIndex());
  if(null != mTabHost){
   int curTabIdx = mTabHost.getCurrentTab();
   mPreSelectedTabIdx = curTabIdx;
   outState.putInt(STATE_SELECTED_TAB_INDEX, curTabIdx);
  }
 }
 
 private int restoreSavedSelectedTabIdx(Bundle savedInstanceState){
  int savedTabIdx = mPreSelectedTabIdx;
  if(null != savedInstanceState){
   if (savedInstanceState.containsKey(STATE_SELECTED_TAB_INDEX)) {
    //getActionBar().setSelectedNavigationItem(savedInstanceState.getInt(STATE_SELECTED_NAVIGATION_ITEM));
    savedTabIdx = savedInstanceState.getInt(STATE_SELECTED_TAB_INDEX);
   }
  }
  return savedTabIdx;
 }
 @Override
 public void onRestoreInstanceState(Bundle savedInstanceState) {
  // Restore the previously serialized current tab position.
  if (savedInstanceState.containsKey(STATE_SELECTED_TAB_INDEX)) {
   //getActionBar().setSelectedNavigationItem(savedInstanceState.getInt(STATE_SELECTED_NAVIGATION_ITEM));
   if(null != mTabHost){
    int savedTabIdx = savedInstanceState.getInt(STATE_SELECTED_TAB_INDEX);
    mTabHost.setCurrentTab(savedTabIdx);
   }
  }
 }
   
    private void generateMainTabUI(){
        mTabHost.setCurrentTab(mPreSelectedTabIdx);
    }
 
 @Override
 public boolean onOptionsItemSelected(MenuItem item) {
     // Handle item selection
     switch (item.getItemId()) {
            ......
         case R.id.menu_settings:
          showPreference();
             return true;
         default:
             return super.onOptionsItemSelected(item);
     }
 }
 private void showPreference(){
  getFragmentManager()
  .beginTransaction()
  .setTransition(
    FragmentTransaction.TRANSIT_FRAGMENT_FADE)
  //.replace(android.R.id.content, new SettingFragment())
  .add(android.R.id.content, new SettingFragment())
  //.replace(android.R.id.tabcontent, new SettingFragment())
  //.replace(R.id.preference_layout, new SettingFragment())
  .addToBackStack(null).commit();
 }
}

 

【总结】

此处对于Activity的recreate会挂的原因是:

Activity代码中之前有和restoreSavedSelectedTabIdx方面的代码,其中有setSelectedNavigationItem

但是该代码是无效的,因为我此处的tab不是用的ActionBar的,是我另外自己用tabHost去实现的。

所以,最简单的办法是:要么去掉该代码

不过,如果继续想要保存tab的index等信息,则需要自己此处额外添加一些代码,就可以了。。



发表评论

电子邮件地址不会被公开。 必填项已用*标注

无觅相关文章插件,快速提升流量