IllegalStateException: Фрагмент <ThisFragment> в настоящее время отсутствует в FragmentManager

У меня возникли проблемы с поиском причины сбоя в моем приложении. У меня есть фрагмент, который отображает ListView, у меня также есть SlidingMenu для поля поиска. И когда я ищу, элементы ListView заселяются на основе результатов поиска. Теперь мое приложение падает, когда я пытаюсь открыть элемент ListView из нового заполненного результата.

Здесь вызывается исключение:

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    getSupportFragmentManager().putFragment(outState, "mContent", mContent); //Exception made here
}

Это из-за библиотеки поддержки? Как это разрешить?

EDIT:

Здесь трассировка стека:

02-05 12:51:53.941: E/AndroidRuntime(11638): FATAL EXCEPTION: main
02-05 12:51:53.941: E/AndroidRuntime(11638): java.lang.IllegalStateException: Fragment MyFragment{436749b0} is not currently in the FragmentManager
02-05 12:51:53.941: E/AndroidRuntime(11638):    at android.support.v4.app.FragmentManagerImpl.putFragment(FragmentManager.java:546)
02-05 12:51:53.941: E/AndroidRuntime(11638):    at com.sample.android.app.SearchListActivity.onSaveInstanceState(SearchListActivity.java:118)
02-05 12:51:53.941: E/AndroidRuntime(11638):    at android.app.Activity.performSaveInstanceState(Activity.java:1137)
02-05 12:51:53.941: E/AndroidRuntime(11638):    at android.app.Instrumentation.callActivityOnSaveInstanceState(Instrumentation.java:1215)
02-05 12:51:53.941: E/AndroidRuntime(11638):    at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:2972)
02-05 12:51:53.941: E/AndroidRuntime(11638):    at android.app.ActivityThread.handleStopActivity(ActivityThread.java:3031)
02-05 12:51:53.941: E/AndroidRuntime(11638):    at android.app.ActivityThread.access$900(ActivityThread.java:138)
02-05 12:51:53.941: E/AndroidRuntime(11638):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
02-05 12:51:53.941: E/AndroidRuntime(11638):    at android.os.Handler.dispatchMessage(Handler.java:99)
02-05 12:51:53.941: E/AndroidRuntime(11638):    at android.os.Looper.loop(Looper.java:213)
02-05 12:51:53.941: E/AndroidRuntime(11638):    at android.app.ActivityThread.main(ActivityThread.java:4787)
02-05 12:51:53.941: E/AndroidRuntime(11638):    at java.lang.reflect.Method.invokeNative(Native Method)
02-05 12:51:53.941: E/AndroidRuntime(11638):    at java.lang.reflect.Method.invoke(Method.java:511)
02-05 12:51:53.941: E/AndroidRuntime(11638):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
02-05 12:51:53.941: E/AndroidRuntime(11638):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:556)
02-05 12:51:53.941: E/AndroidRuntime(11638):    at dalvik.system.NativeStart.main(Native Method)

ИЗМЕНИТЬ 2: Здесь моя активность:

private Fragment mFragment;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

            ..........

    params = new Bundle();
    params.putInt("id", id);

    // set the Above View Fragment
    if (savedInstanceState != null)
        mFragment = getSupportFragmentManager().getFragment(
                savedInstanceState, "mFragment");
    else {
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager
                .beginTransaction();
        SampleListFragment fragment = new SampleListFragment();
        fragment.setArguments(params);
        fragmentTransaction.add(R.id.list_fragment, fragment);
        fragmentTransaction.commit();
    }

    if (mFragment == null) {
        mFragment = new SampleListFragment();
        mFragment.setArguments(params);
    }
    getSupportFragmentManager().beginTransaction()
            .replace(R.id.list_fragment, mFragment).commit();

    // set the Behind View Fragment
    Fragment searchFragment = new SampleSearchFragment();
    searchFragment.setArguments(params);

    getSupportFragmentManager().beginTransaction()
            .replace(R.id.activity_search, searchFragment)
            .commit();
}


@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    getSupportFragmentManager().putFragment(outState, "mFragment",
            mFragment);
}

И в моем SampleListFragment у меня есть этот метод:

public static boolean isNetworkAvailable(Activity activity) {
    ConnectivityManager connectivity = (ConnectivityManager) activity
            .getSystemService(Context.CONNECTIVITY_SERVICE);
    if (connectivity == null) {
        return false;
    } else {
        NetworkInfo[] info = connectivity.getAllNetworkInfo();
        if (info != null) {
            for (int i = 0; i < info.length; i++) {
                if (info[i].getState() == NetworkInfo.State.CONNECTED) {
                    return true;
                }
            }
        }
    }
    return false;
}

Внутри Asynctask:

..........
@Override
protected void onPostExecute(String result) {
    super.onPostExecute(null);

    if (null != pDialog && pDialog.isShowing()) {
        pDialog.dismiss();
    }

    if (isNetworkAvailable(getActivity())) { //Triggered NPE

Из здесь, как узнать, привязан ли getActivity() к родительскому действию, прежде чем вызывать его?

Ответ 1

Перед сохранением фрагмента в onSaveInstanceState обязательно проверьте, добавлен ли фрагмент в диспетчер фрагментов

@Override 
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    if (mFragment.isAdded()){
        getSupportFragmentManager().putFragment(outState, "mFragment", mFragment); 
    }
} 

Ответ 2

Я тоже сталкиваюсь с такой же проблемой. КОГДА я попытался поместить фрагмент в bundleState в

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    getSupportFragmentManager().putFragment(outState, "mContent",   mContent); //Exception made here
}

Я проверил реализацию метода putFragment() в FragmentManager. Это похоже на

 @Override
 public void putFragment(Bundle bundle, String key, Fragment fragment) {
    if (fragment.mIndex < 0) {
         throwException(new IllegalStateException("Fragment " + fragment
                    + " is not currently in the FragmentManager"));
    }
    bundle.putInt(key, fragment.mIndex);
  }

где mIndex - индекс фрагмента в массив активных фрагментов. Поэтому, если mIndex < 0 означает, что фрагмент в настоящий момент не активен. Так как @FelipeConde предположил, что проверка mFragment.isAdded() может быть лучшим решением.

Ответ 3

Недавно я столкнулся с той же проблемой. В моем случае я забыл установить mFragment, когда вызывается действие onBackPressed(). То есть, когда пользователь перемещается через A → B → C, mFragment меняется соответственно на A, затем B и, наконец, C. Однако, когда задняя часть нажата, текущий фрагмент изменяется обратно на B, затем A, но mFragment еще C. Таким образом, во время onSaveInstanceState активность пытается сохранить C, который больше не находится в FragmentManager.

Главное, вы, вероятно, меняете (добавляете или удаляете) текущий [отображаемый] фрагмент без соответствующего изменения mFragment.

Ответ 4

В моем случае, Фрагменты, которые добавлены в ViewPager через FragmentPagerAdapter, чтобы иметь несколько вкладок и 1 фрагмент на вкладку.

    List<Android.Support.V4.App.Fragment> lsFragments = new List<Android.Support.V4.App.Fragment>();
    lsFragments.Add(m_FragmentListDocument);
    lsFragments.Add(m_FragmentListNote);
    lsFragments.Add(m_FragmentListRenvoi);

    m_viewPager.Adapter = new TabsFragmentPagerAdapter(SupportFragmentManager, lsFragments, lsTitles);

В моем OnSaveInstanceState я хотел сохранить все вкладки, но 1 вкладка выбрала Exception Java.Lang.IllegalStateException: Fragment is not currently in the FragmentManager:

protected override void OnSaveInstanceState(Bundle outState)
{
    base.OnSaveInstanceState(outState);

    SupportFragmentManager.PutFragment(outState, "FragmentListDocument", m_FragmentListDocument);
    SupportFragmentManager.PutFragment(outState, "FragmentListNote", m_FragmentListNote);
    SupportFragmentManager.PutFragment(outState, "FragmentListRenvoi", m_FragmentListRenvoi);
}

Это связано с ViewPager: ViewPager загружает текущий фрагмент, показанный на экране, и (по умолчанию) тот, что находится слева и справа.

Итак, в этом случае я модифицировал ViewPager, чтобы установить OffscreenPageLimit достаточно высоким, чтобы загружать все фрагменты при запуске. Затем фрагменты были добавлены в SupportFragmentManager, и исключение не было добавлено в OnSaveInstanceState.

m_viewPager.OffscreenPageLimit = 4;

Надеюсь, это поможет...