Сохранение состояния фрагмента в Activity - PullRequest
0 голосов
/ 20 февраля 2020

Я получаю сообщение об ошибке ниже, когда пытаюсь сохранить состояние моих фрагментов в моей основной деятельности:

java.lang.IllegalStateException: Fragment MarketviewFragment{c5e0f0d} is not currently in the FragmentManager
    at androidx.fragment.app.FragmentManagerImpl.putFragment(FragmentManager.java:923)
    at com.shoob.capstone.android.crypfolio.MainActivity.onSaveInstanceState(MainActivity.java:308)
    at android.app.Activity.performSaveInstanceState(Activity.java:1608)
    at android.app.Instrumentation.callActivityOnSaveInstanceState(Instrumentation.java:1443)
    at android.app.ActivityThread.callActivityOnSaveInstanceState(ActivityThread.java:5038)
    at android.app.ActivityThread.callActivityOnStop(ActivityThread.java:4372)
    at android.app.ActivityThread.handleRelaunchActivityInner(ActivityThread.java:4986)
    at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4922)
    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:1926)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:6986)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1445)

В моей основной деятельности у меня есть 4 возможных фрагмента, которые отображаются только один в время. Я сохраняю ссылку на фрагменты в основном задании и отображаю их по мере необходимости:

private MarketviewFragment marketviewFragment;
private WatchlistFragment watchlistFragment;
private PortfolioFragment portfolioFragment;
private DetailsFragment detailsFragment;

Я устанавливаю текущий отображаемый фрагмент с помощью приведенного ниже кода (только один фрагмент отображается одновременно):

//fragment is an instance of one of the 4 types of fragments above
private void setFragment(Fragment fragment) {
    FragmentManager fm = getSupportFragmentManager();

    if (fm.findFragmentById(R.id.frag_main) != null) {
        fm.beginTransaction()
                .replace(R.id.frag_main, fragment)
                .commit();
    } else {
        fm.beginTransaction()
                .add(R.id.frag_main, fragment)
                .commit();
    }
}

Вот как я устанавливаю каждый фрагмент (один пример, то же самое для других типов):

private void setPortfolioFragment() {
    if (portfolioFragment == null) {
        portfolioFragment = PortfolioFragment.newInstance();
    }
    setFragment(portfolioFragment);
}

Теперь к моему вопросу. Как мне сохранить состояние всех этих фрагментов? Я хочу сохранить их все в связке, чтобы восстановить их при воссоздании основной активности (например, при ротации).

То, как я это делаю сейчас, похоже, не работает. правильный способ сделать это?

Состояние сохранения:

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    if (marketviewFragment != null) {
        getSupportFragmentManager().putFragment(outState, KEY_BUNDLE_MARKETVIEW_FRAGMENT, marketviewFragment);
    }
    if (watchlistFragment != null) {
        getSupportFragmentManager().putFragment(outState, KEY_BUNDLE_WATCHLIST_FRAGMENT, watchlistFragment);
    }
    if (portfolioFragment != null) {
        getSupportFragmentManager().putFragment(outState, KEY_BUNDLE_PORTFOLIO_FRAGMENT, portfolioFragment);
    }
    if (detailsFragment != null) {
        getSupportFragmentManager().putFragment(outState, KEY_BUNDLE_DETAILS_FRAGMENT, detailsFragment);
    }

}

Состояние восстановления:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    if (savedInstanceState != null) {
        marketviewFragment = (MarketviewFragment)getSupportFragmentManager().getFragment(savedInstanceState, KEY_BUNDLE_MARKETVIEW_FRAGMENT);
        watchlistFragment = (WatchlistFragment)getSupportFragmentManager().getFragment(savedInstanceState, KEY_BUNDLE_WATCHLIST_FRAGMENT);
        portfolioFragment = (PortfolioFragment)getSupportFragmentManager().getFragment(savedInstanceState, KEY_BUNDLE_PORTFOLIO_FRAGMENT);
        detailsFragment = (DetailsFragment)getSupportFragmentManager().getFragment(savedInstanceState, KEY_BUNDLE_DETAILS_FRAGMENT);

    }
}

Ответы [ 2 ]

0 голосов
/ 20 февраля 2020

Ваша деятельность не должна обрабатывать сохранение состояния для каждого фрагмента. Вы должны позволить каждому фрагменту обрабатывать сохранение своего собственного состояния, переопределяя onSaveInstanceState () в каждом классе фрагмента:

@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
    super.onSaveInstanceState(outState);
    // save fragment state here
}

Кроме того, сохранение жестких ссылок на все ваши фрагменты в вашей деятельности не является хорошей идеей.

Редактировать: Посмотрев на ваш вопрос еще раз, я больше понимаю, что вы пытаетесь сделать. Вы пытаетесь сохранить и восстановить фактические экземпляры ваших фрагментов. ОС Android сделает это автоматически для вас, и вы пытаетесь помешать этому процессу. Опять же, тот факт, что вы храните фрагменты как переменные экземпляра, является частью проблемы и заставляет вас делать то, что вам обычно не нужно делать.

0 голосов
/ 20 февраля 2020

Вы должны сохранять его каждый раз, когда отсоединяете фрагмент. также, пожалуйста, используйте detach / attach вместо replace на fragmentManager

, другое дело в том, что FragmentManager должен восстанавливать фрагменты самостоятельно. Лично я бы сделал это с помощью FragmentPagerAdapter и просто переключил бы видимый.

Лучший и самый простой способ - подключить все фрагменты к FragmentManager и просто контролировать видимость. Благодаря этому сохранение / восстановление будет выполнено автоматически

...