【背景】
之前折腾了:
【基本解决】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
如图:
对应代码是:
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等信息,则需要自己此处额外添加一些代码,就可以了。。
转载请注明:在路上 » 【已解决】Android中getActivity().recreate()时出错:java.lang.IllegalStateException: setSelectedNavigationIndex not valid for current navigation mode