getSavedInstanceState() 和 onViewStateRestored() 包的问题
Problems with getSavedInstanceState() and onViewStateRestored() bundle
我在 Activity 中有一个片段,当设备旋转时,会调用 onSaveInstanceState() 和 onViewStateRestored()。
onSaveInstanceState():
@Override
public void onSaveInstanceState(Bundle outState){
Log.e("Fragment", "Called onSaveInstanceState");
outState = getSavedInstanceState();
super.onSaveInstanceState(outState);
}
这是在 onSaveInstanceState() 中设置 outState 包的原因:
public static Bundle getSavedInstanceState(){
Bundle saveState = new Bundle();
//Save view states
saveState.putBoolean("startButtonVisible", buttonStart.getVisibility() == View.VISIBLE);
saveState.putBoolean("stopButtonVisible", buttonStop.getVisibility() == View.VISIBLE);
saveState.putBoolean("resetButtonVisible", buttonReset.getVisibility() == View.VISIBLE);
saveState.putBoolean("saveButtonVisible", buttonSave.getVisibility() == View.VISIBLE);
saveState.putBoolean("openLatestFileButtonVisible", buttonOpenLatestFile.getVisibility() == View.VISIBLE);
saveState.putBoolean("editTextStartValueVisible", editTextStartValue.isEnabled());
saveState.putBoolean("buttonStartValueDownVisible", buttonStartValueDown.isEnabled());
saveState.putBoolean("buttonStartValueUpVisible", buttonStartValueUp.isEnabled());
saveState.putBoolean("editTextEndValueVisible", editTextEndValue.isEnabled());
saveState.putBoolean("buttonEndValueDownVisible", buttonEndValueDown.isEnabled());
saveState.putBoolean("buttonEndValueUpVisible", buttonEndValueUp.isEnabled());
return saveState;
}
这样可以正确保存数据,但是当调用 onViewStateRestored() 时,数据不正确。
@Override
public void onViewStateRestored(Bundle savedInstanceState){
Log.e("Fragment", "Called onViewStateRestored");
super.onViewStateRestored(savedInstanceState);
//Restore view states
if (savedInstanceState != null){
restoreInstanceState(savedInstanceState);
if (buttonReset.getVisibility() == View.VISIBLE){
updateUi();
}
}
}
调用 onViewStateRestored() 时,它还会调用 restoreInstanceState(),这是用来恢复每个视图状态的。
public static void restoreInstanceState(Bundle savedInstanceState){
buttonStart.setVisibility(savedInstanceState.getBoolean("startButtonVisible") ? View.VISIBLE : View.INVISIBLE);
buttonStop.setVisibility(savedInstanceState.getBoolean("stopButtonVisible") ? View.VISIBLE : View.INVISIBLE);
buttonReset.setVisibility(savedInstanceState.getBoolean("resetButtonVisible") ? View.VISIBLE : View.INVISIBLE);
buttonSave.setVisibility(savedInstanceState.getBoolean("saveButtonVisible") ? View.VISIBLE : View.INVISIBLE);
buttonOpenLatestFile.setVisibility(savedInstanceState.getBoolean("openLatestFileButtonVisible") ? View.VISIBLE : View.INVISIBLE);
editTextStartValue.setEnabled(savedInstanceState.getBoolean("editTextStartValueVisible"));
buttonStartValueDown.setEnabled(savedInstanceState.getBoolean("buttonStartValueDownVisible"));
buttonStartValueDown.setImageResource(buttonStartValueDown.isEnabled() ? R.drawable.ic_arrow_down : R.drawable.ic_arrow_down_gray);
buttonStartValueUp.setEnabled(savedInstanceState.getBoolean("buttonStartValueUpVisible"));
buttonStartValueUp.setImageResource(buttonStartValueUp.isEnabled() ? R.drawable.ic_arrow_up : R.drawable.ic_arrow_up_gray);
editTextEndValue.setEnabled(savedInstanceState.getBoolean("editTextEndValueVisible"));
buttonEndValueDown.setEnabled(savedInstanceState.getBoolean("buttonEndValueDownVisible"));
buttonEndValueDown.setImageResource(buttonEndValueDown.isEnabled() ? R.drawable.ic_arrow_down : R.drawable.ic_arrow_down_gray);
buttonEndValueUp.setEnabled(savedInstanceState.getBoolean("buttonEndValueUpVisible"));
buttonEndValueUp.setImageResource(buttonEndValueUp.isEnabled() ? R.drawable.ic_arrow_up : R.drawable.ic_arrow_up_gray);
Log.e("Fragment", "Restored view visibility");
}
为什么调用onViewStateRestored()时数据不正确?所有的视图都变得不可见,不管它们之前是什么。保存状态和恢复状态的bundle不一样吗?
然而,当调用 fragmentManager.beginTransaction().replace(R.id.content_frame, CustomFragmentManager.savedFilesFragment).commit();
然后手动调用 onViewStateRestored() 时,所有这些代码都有效。
编辑: 更改了字段名称。
解决方案: 我已经用 outState.putAll(getSavedInstanceState());
替换了 outState = new Bundle(getSavedInstanceState());
,现在可以使用了。没有必要调用 setRetainInstance(true);
。
我怀疑这与您的方法签名有关。为什么要使用 static
?静态方法不能访问实例成员。这个:
public static Bundle getSavedInstanceState()
public static void restoreInstanceState(Bundle savedInstanceState)
应该是:
public Bundle getSavedInstanceState()
public void restoreInstanceState(Bundle savedInstanceState)
其次,您的字段名称非常糟糕un-Java-like。这个:
BTN_startValueDown
应该是(例如):
btnStartValueDown
第一次编辑
早该想到这一点。由于您只是想保留片段的状态,因此只需在片段的 onCreate()
中调用 setRetainInstance(true)
。参见 here。
第二次编辑
另一个回答者是对的:您不应该为 out-state 创建另一个 Bundle。如果您真的想在单独的方法中创建该 Bundle,请改用此方法:
outState.putAll(getSavedInstanceState());
你不应该自己手动创建状态包,使用在 onSaveInstanceState() 方法中传递的 outState 对象并在 onCreate() 方法中恢复。此外,您应该在片段的 onCreate() 中调用 setRetainInstance(true)。
我在 Activity 中有一个片段,当设备旋转时,会调用 onSaveInstanceState() 和 onViewStateRestored()。
onSaveInstanceState():
@Override
public void onSaveInstanceState(Bundle outState){
Log.e("Fragment", "Called onSaveInstanceState");
outState = getSavedInstanceState();
super.onSaveInstanceState(outState);
}
这是在 onSaveInstanceState() 中设置 outState 包的原因:
public static Bundle getSavedInstanceState(){
Bundle saveState = new Bundle();
//Save view states
saveState.putBoolean("startButtonVisible", buttonStart.getVisibility() == View.VISIBLE);
saveState.putBoolean("stopButtonVisible", buttonStop.getVisibility() == View.VISIBLE);
saveState.putBoolean("resetButtonVisible", buttonReset.getVisibility() == View.VISIBLE);
saveState.putBoolean("saveButtonVisible", buttonSave.getVisibility() == View.VISIBLE);
saveState.putBoolean("openLatestFileButtonVisible", buttonOpenLatestFile.getVisibility() == View.VISIBLE);
saveState.putBoolean("editTextStartValueVisible", editTextStartValue.isEnabled());
saveState.putBoolean("buttonStartValueDownVisible", buttonStartValueDown.isEnabled());
saveState.putBoolean("buttonStartValueUpVisible", buttonStartValueUp.isEnabled());
saveState.putBoolean("editTextEndValueVisible", editTextEndValue.isEnabled());
saveState.putBoolean("buttonEndValueDownVisible", buttonEndValueDown.isEnabled());
saveState.putBoolean("buttonEndValueUpVisible", buttonEndValueUp.isEnabled());
return saveState;
}
这样可以正确保存数据,但是当调用 onViewStateRestored() 时,数据不正确。
@Override
public void onViewStateRestored(Bundle savedInstanceState){
Log.e("Fragment", "Called onViewStateRestored");
super.onViewStateRestored(savedInstanceState);
//Restore view states
if (savedInstanceState != null){
restoreInstanceState(savedInstanceState);
if (buttonReset.getVisibility() == View.VISIBLE){
updateUi();
}
}
}
调用 onViewStateRestored() 时,它还会调用 restoreInstanceState(),这是用来恢复每个视图状态的。
public static void restoreInstanceState(Bundle savedInstanceState){
buttonStart.setVisibility(savedInstanceState.getBoolean("startButtonVisible") ? View.VISIBLE : View.INVISIBLE);
buttonStop.setVisibility(savedInstanceState.getBoolean("stopButtonVisible") ? View.VISIBLE : View.INVISIBLE);
buttonReset.setVisibility(savedInstanceState.getBoolean("resetButtonVisible") ? View.VISIBLE : View.INVISIBLE);
buttonSave.setVisibility(savedInstanceState.getBoolean("saveButtonVisible") ? View.VISIBLE : View.INVISIBLE);
buttonOpenLatestFile.setVisibility(savedInstanceState.getBoolean("openLatestFileButtonVisible") ? View.VISIBLE : View.INVISIBLE);
editTextStartValue.setEnabled(savedInstanceState.getBoolean("editTextStartValueVisible"));
buttonStartValueDown.setEnabled(savedInstanceState.getBoolean("buttonStartValueDownVisible"));
buttonStartValueDown.setImageResource(buttonStartValueDown.isEnabled() ? R.drawable.ic_arrow_down : R.drawable.ic_arrow_down_gray);
buttonStartValueUp.setEnabled(savedInstanceState.getBoolean("buttonStartValueUpVisible"));
buttonStartValueUp.setImageResource(buttonStartValueUp.isEnabled() ? R.drawable.ic_arrow_up : R.drawable.ic_arrow_up_gray);
editTextEndValue.setEnabled(savedInstanceState.getBoolean("editTextEndValueVisible"));
buttonEndValueDown.setEnabled(savedInstanceState.getBoolean("buttonEndValueDownVisible"));
buttonEndValueDown.setImageResource(buttonEndValueDown.isEnabled() ? R.drawable.ic_arrow_down : R.drawable.ic_arrow_down_gray);
buttonEndValueUp.setEnabled(savedInstanceState.getBoolean("buttonEndValueUpVisible"));
buttonEndValueUp.setImageResource(buttonEndValueUp.isEnabled() ? R.drawable.ic_arrow_up : R.drawable.ic_arrow_up_gray);
Log.e("Fragment", "Restored view visibility");
}
为什么调用onViewStateRestored()时数据不正确?所有的视图都变得不可见,不管它们之前是什么。保存状态和恢复状态的bundle不一样吗?
然而,当调用 fragmentManager.beginTransaction().replace(R.id.content_frame, CustomFragmentManager.savedFilesFragment).commit();
然后手动调用 onViewStateRestored() 时,所有这些代码都有效。
编辑: 更改了字段名称。
解决方案: 我已经用 outState.putAll(getSavedInstanceState());
替换了 outState = new Bundle(getSavedInstanceState());
,现在可以使用了。没有必要调用 setRetainInstance(true);
。
我怀疑这与您的方法签名有关。为什么要使用 static
?静态方法不能访问实例成员。这个:
public static Bundle getSavedInstanceState()
public static void restoreInstanceState(Bundle savedInstanceState)
应该是:
public Bundle getSavedInstanceState()
public void restoreInstanceState(Bundle savedInstanceState)
其次,您的字段名称非常糟糕un-Java-like。这个:
BTN_startValueDown
应该是(例如):
btnStartValueDown
第一次编辑
早该想到这一点。由于您只是想保留片段的状态,因此只需在片段的 onCreate()
中调用 setRetainInstance(true)
。参见 here。
第二次编辑
另一个回答者是对的:您不应该为 out-state 创建另一个 Bundle。如果您真的想在单独的方法中创建该 Bundle,请改用此方法:
outState.putAll(getSavedInstanceState());
你不应该自己手动创建状态包,使用在 onSaveInstanceState() 方法中传递的 outState 对象并在 onCreate() 方法中恢复。此外,您应该在片段的 onCreate() 中调用 setRetainInstance(true)。