【问题标题】:Unable to save Fragment state with onSaveInstanceState无法使用 onSaveInstanceState 保存片段状态
【发布时间】:2019-08-06 20:34:35
【问题描述】:

我有一个管理两个 FragmentMainActivityInputDataFragment(在应用程序打开时显示的那个),其中包含一系列EditTextResultsFragment,在单击按钮后替换 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)

【问题讨论】:

  • 如果你的EditText 有一个android:id,那么它的状态会被自动保存和恢复。您不需要任何 onSaveInstanceState() 代码。
  • 如果你的 EditTexts 有 id,那么你不需要手动保存它们,因为 super.onSaveInstanceState() 已经处理了。您应该只覆盖onSaveInstanceState()(并调用super)来保存活动/片段中的变量,如果您的活动/片段被销毁并重新创建,则需要保存/恢复。检查inthecheesefactory.com/blog/…
  • 我的 EditTexts 在我处于 InputDataFragment 并旋转设备时正确保存它们的状态。但问题是,如果我导航到 ResultsFragment,然后旋转设备,当我返回 InputDataFragment 时,EditTexts 是空的。正如@fernandospr 提供的链接中所建议的那样,我给了每个EditText 一个android:id,但它仍然不起作用
  • 另外,如果我从 InputDataFragment 导航到 ResultsFragment 并返回到 InputDataFragment,我的 EditTexts 会正确保存它们的状态旋转设备

标签: android android-fragments onsaveinstancestate


【解决方案1】:

我解决了,问题就在这里

@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 是解决方案的情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多