无法使用 onSaveInstanceState 保存片段状态
Unable to save Fragment state with onSaveInstanceState
我有一个管理两个 Fragments 的 MainActivity:InputDataFragment(显示的是在应用程序打开时),其中包含一系列 EditText 和 ResultsFragment,它取代了 InputDataFragment 之后单击一个按钮。
我想将数据保存在 EditText 字段中,这样,即使在屏幕旋转等配置更改之后,如果我从 ResultsFragment 导航回 InputDataFragment,我可以用那些数据重新填充。
这是我用来从 InputDataFragment 导航到 ResultsFragment:
的代码
@Override
public void onCalculate(String firstElement, String secondElement) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
ResultsFragment resultsFragment = new ResultsFragment();
fragmentTransaction.replace(R.id.container, resultsFragment);
fragmentTransaction.commit();
}
这是我在 InputDataFragment
中保存值的地方
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
// Check if there's something to retain before putting it into outState Bundle
if (!firstEditText.getText().toString().isEmpty()) {
outState.putString("firstElement", firstEditText.getText().toString());
Log.d(LOG_TAG, "Power saved");
}
if (!secondEditText.getText().toString().isEmpty()) {
outState.putString("secondElement", secondEditText.getText().toString());
}
}
这是我检索它们的地方
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null) {
firstEditText.setText(savedInstanceState.getString("firstElement"));
secondEditText.setText(savedInstanceState.getString("secondElement"));
}
}
我已经尝试按照这些 Stack Overflow 问题的已接受答案中的建议进行操作,保存和恢复我的 Fragment 引用:
Once for all, how to correctly save instance state of Fragments in back stack?
Using onSaveInstanceState with fragments in backstack?
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
getSupportFragmentManager().putFragment(outState, "dataFragment", dataFragment);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
if (savedInstanceState != null) {
dataFragment = (InputDataFragment) getSupportFragmentManager().getFragment(savedInstanceState, "dataFragment");
} else {
dataFragment = new InputDataFragment();
}
fragmentTransaction.add(R.id.container, dataFragment);
fragmentTransaction.commit();
}
当 Fragment 中调用 onActivityCreated
时,Bundle 中的值正确存在,因为我已尝试登录他们
问题是,当我在 ResultFragment 中并旋转时,我在 onSaveInstanceState
中调用 putFragment
的行中出现错误设备。
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.mycompany.myproject, PID: 20161
java.lang.IllegalStateException: Fragment InputDataFragment{679fd26} is not currently in the FragmentManager
at androidx.fragment.app.FragmentManagerImpl.putFragment(FragmentManager.java:923)
at com.mycompany.myproject.MainActivity.onSaveInstanceState(MainActivity.java:21)
at android.app.Activity.performSaveInstanceState(Activity.java:1646)
at android.app.Instrumentation.callActivityOnSaveInstanceState(Instrumentation.java:1508)
at android.app.ActivityThread.callActivityOnSaveInstanceState(ActivityThread.java:5476)
at android.app.ActivityThread.callActivityOnStop(ActivityThread.java:4792)
at android.app.ActivityThread.handleRelaunchActivityInner(ActivityThread.java:5424)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:5342)
at android.app.servertransaction.ActivityRelaunchItem.execute(ActivityRelaunchItem.java:69)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2155)
at android.os.Handler.dispatchMessage(Handler.java:109)
at android.os.Looper.loop(Looper.java:207)
at android.app.ActivityThread.main(ActivityThread.java:7539)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:958)
我解决了,问题就在这里
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
if (savedInstanceState != null) {
dataFragment = (InputDataFragment) getSupportFragmentManager().getFragment(savedInstanceState, "dataFragment");
} else {
dataFragment = new InputDataFragment();
}
fragmentTransaction.add(R.id.container, dataFragment);
fragmentTransaction.commit();
}
当我在 ResultsFragment 中旋转设备时,会调用 Activity onCreate
方法。即使我从 Bundle 返回了之前的 InputDataFragment,调用 FragmentTransaction.add()
导致数据丢失。
将 FragmentTransaction
代码移动到 savedInstanceState == null 的情况下是解决方案。
我有一个管理两个 Fragments 的 MainActivity:InputDataFragment(显示的是在应用程序打开时),其中包含一系列 EditText 和 ResultsFragment,它取代了 InputDataFragment 之后单击一个按钮。
我想将数据保存在 EditText 字段中,这样,即使在屏幕旋转等配置更改之后,如果我从 ResultsFragment 导航回 InputDataFragment,我可以用那些数据重新填充。
这是我用来从 InputDataFragment 导航到 ResultsFragment:
@Override
public void onCalculate(String firstElement, String secondElement) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
ResultsFragment resultsFragment = new ResultsFragment();
fragmentTransaction.replace(R.id.container, resultsFragment);
fragmentTransaction.commit();
}
这是我在 InputDataFragment
中保存值的地方@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
// Check if there's something to retain before putting it into outState Bundle
if (!firstEditText.getText().toString().isEmpty()) {
outState.putString("firstElement", firstEditText.getText().toString());
Log.d(LOG_TAG, "Power saved");
}
if (!secondEditText.getText().toString().isEmpty()) {
outState.putString("secondElement", secondEditText.getText().toString());
}
}
这是我检索它们的地方
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null) {
firstEditText.setText(savedInstanceState.getString("firstElement"));
secondEditText.setText(savedInstanceState.getString("secondElement"));
}
}
我已经尝试按照这些 Stack Overflow 问题的已接受答案中的建议进行操作,保存和恢复我的 Fragment 引用:
Once for all, how to correctly save instance state of Fragments in back stack?
Using onSaveInstanceState with fragments in backstack?
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
getSupportFragmentManager().putFragment(outState, "dataFragment", dataFragment);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
if (savedInstanceState != null) {
dataFragment = (InputDataFragment) getSupportFragmentManager().getFragment(savedInstanceState, "dataFragment");
} else {
dataFragment = new InputDataFragment();
}
fragmentTransaction.add(R.id.container, dataFragment);
fragmentTransaction.commit();
}
当 Fragment 中调用 onActivityCreated
时,Bundle 中的值正确存在,因为我已尝试登录他们
问题是,当我在 ResultFragment 中并旋转时,我在 onSaveInstanceState
中调用 putFragment
的行中出现错误设备。
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.mycompany.myproject, PID: 20161
java.lang.IllegalStateException: Fragment InputDataFragment{679fd26} is not currently in the FragmentManager
at androidx.fragment.app.FragmentManagerImpl.putFragment(FragmentManager.java:923)
at com.mycompany.myproject.MainActivity.onSaveInstanceState(MainActivity.java:21)
at android.app.Activity.performSaveInstanceState(Activity.java:1646)
at android.app.Instrumentation.callActivityOnSaveInstanceState(Instrumentation.java:1508)
at android.app.ActivityThread.callActivityOnSaveInstanceState(ActivityThread.java:5476)
at android.app.ActivityThread.callActivityOnStop(ActivityThread.java:4792)
at android.app.ActivityThread.handleRelaunchActivityInner(ActivityThread.java:5424)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:5342)
at android.app.servertransaction.ActivityRelaunchItem.execute(ActivityRelaunchItem.java:69)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2155)
at android.os.Handler.dispatchMessage(Handler.java:109)
at android.os.Looper.loop(Looper.java:207)
at android.app.ActivityThread.main(ActivityThread.java:7539)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:958)
我解决了,问题就在这里
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
if (savedInstanceState != null) {
dataFragment = (InputDataFragment) getSupportFragmentManager().getFragment(savedInstanceState, "dataFragment");
} else {
dataFragment = new InputDataFragment();
}
fragmentTransaction.add(R.id.container, dataFragment);
fragmentTransaction.commit();
}
当我在 ResultsFragment 中旋转设备时,会调用 Activity onCreate
方法。即使我从 Bundle 返回了之前的 InputDataFragment,调用 FragmentTransaction.add()
导致数据丢失。
将 FragmentTransaction
代码移动到 savedInstanceState == null 的情况下是解决方案。