IllegalStateException:片段<thisfragment>当前不在FragmentManager中</thisfragment>

时间:2014-02-05 03:55:46

标签: android android-fragments nullpointerexception android-support-library illegalstateexception

我无法在应用中跟踪崩溃原因。我有一个显示ListView的片段,我还有一个搜索字段SlidingMenu。当我搜索时,ListView项目将根据搜索结果重新填充。现在,当我尝试从新填充的结果中打开ListView项时,我的应用程序崩溃了。

此处触发异常:

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

这是因为支持库吗?我该如何解决这个问题?

修改

这是堆栈跟踪:

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

here开始,如何在调用之前知道getActivity()是否已附加到父活动?

5 个答案:

答案 0 :(得分:30)

onSaveInstanceState中保存片段之前,请确保检查片段是否已添加到片段管理器

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

答案 1 :(得分:1)

我也面临同样的问题。当我尝试将片段放在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()可能是最佳解决方案。

答案 2 :(得分:1)

最近,我遇到了同样的问题。 就我而言,我忘了在调用活动onBackPressed()时设置mFragment。也就是说,当用户浏览A - &gt; B - &gt; C,mFragment相应地更改为A,然后是B,最后是C.但是,当按下后退时,当前片段反向更改为B,然后是A,但mFragment仍为C.因此,在onSaveInstanceState期间,活动尝试保存C它不再出现在FragmentManager中了。

  

重点是,您可能在不适当更改mFragment的情况下更改(添加或删除)当前[显示]片段。

答案 3 :(得分:1)

在我的情况下,我有2个片段( PopularMoviesFragment和TopRatedMoviesFragement ), PopularMoviesFragment 填充在Activity的onCreate中,另一个则单击< strong> BottomNavigationView 。

因此,当我打开应用程序并且没有单击 BottomNavigationView 时,如果我最小化(或导航到其他应用程序),则会收到此异常

  

java.lang.IllegalStateException:Fragment TopRatedMoviesFragement {79d8905}当前不在FragmentManager中

我在onCreate()中的代码为

if (currentSelectedbottomNavigation.equals(FRAGMENT_1)) {

        fragmentManager.beginTransaction()
                .replace(R.id.containerw, fragment_1, FRAGMENT_1)
                .addToBackStack(null)
                .commit();
    }else if (currentSelectedbottomNavigation.equals(FRAGMENT_2)){   

        fragmentManager.beginTransaction()
                .replace(R.id.container, fragment_2, FRAGMENT_2)
                .addToBackStack(null)
                .commit();
    }

因此,我所做的只是添加了 TopRatedMoviesFragement ,然后将其替换为 PopularMoviesFragment ,如下面的代码所示。

if (currentSelectedbottomNavigation.equals(FRAGMENT_1)) {

        fragmentManager.beginTransaction()
                .add(R.id.container, fragment_2, FRAGMENT_2)
                // Its been added to avoid Fragment is not currently in the FragmentManager
                .replace(R.id.container, fragment_1, FRAGMENT_1)
                .addToBackStack(null)
                .commit();
    }else if (currentSelectedbottomNavigation.equals(FRAGMENT_2)){  

        fragmentManager.beginTransaction()
                .replace(R.id.container, fragment_2, FRAGMENT_2)
                .addToBackStack(null)
                .commit();
    }

希望这也有帮助。 :)

答案 4 :(得分:0)

就我而言,片段通过FragmentPagerAdapter添加到ViewPager,以便有多个标签,每个标签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个标签正在抛出异常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;

希望它会有所帮助...