造成java.IllegalStateException错误,没有活动,导航到片段第二次只有当(ca

2019-07-20 01:41发布

我得到一个十分不解错误,我不知道如何甚至开始学习的。

我有一个活动一个简单的应用程序,视图与片段实施。 一个片段具有其内部的ViewPager; 所以我决定,我想用getChildFragmentManager类V4支持库。 我也不得不使用ActionBarSherlock,这就造成一个问题,因为它不与V4库V11发货。

我解决了这个问题通过与V11库替换ABS V4的支持库和编译一切,似乎是工作,包括ViewPager。

这里是陌生的一部分:

第一次与ViewPager片段打开,它工作正常; 但第二次,导航到,应用程序崩溃,给人一种无用的堆栈跟踪。 从调试,我发现问题是由getChildFragmentManager返回的FragmentManager; 它抛出的无活动错误。

没有任何人有任何想法可能是什么造成的?

我会后,你认为是相关的代码。

谢谢你,大卫

Answer 1:

我跟着链接jeremyvillalobos答案 (这是非常有益的),导致我这个解决办法 。

public class CustomFragment extends Fragment {
    private static final Field sChildFragmentManagerField;

    static {
        Field f = null;
        try {
            f = Fragment.class.getDeclaredField("mChildFragmentManager");
            f.setAccessible(true);
        } catch (NoSuchFieldException e) {
            Log.e(LOGTAG, "Error getting mChildFragmentManager field", e);
        }
        sChildFragmentManagerField = f;
    }

    @Override
    public void onDetach() {
        super.onDetach();

        if (sChildFragmentManagerField != null) {
            try {
                sChildFragmentManagerField.set(this, null);
            } catch (Exception e) {
                Log.e(LOGTAG, "Error setting mChildFragmentManager field", e);
            }
        }
    }

    ...
}

它为我好,而不需要重新实例片段。



Answer 2:

这似乎是一个错误报道

https://code.google.com/p/android/issues/detail?id=42601

变量

FragmentManagerImpl mChildFragmentManager;

在Fragment.java未设置为空的分离。 所以片段下一次加载时,变量仍指向最后的父母。

如在该线程上所讨论的,一个解决办法是重新实例化片段。

就我而言,我是片段之间在动作条选项卡切换。 陷入困境的片段具有嵌套片段和回来的文件加载片段时被撞毁的应用程序。 因此,这是变通的代码:

class MainTabsListener implements ActionBar.TabListener {
    public Fragment fragment;
    public int TabPosition;

    public MainTabsListener(Fragment fragment, int tab_position) {
        this.fragment = fragment;
        TabPosition = tab_position;
    }

    @Override
    public void onTabReselected(Tab tab, FragmentTransaction ft) {
    }

    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        CurrentFragment = fragment;
        CurrentTabSelectedPos = TabPosition;

        /**
         * This is a work-around for Issue 42601
         * https://code.google.com/p/android/issues/detail?id=42601
         * 
         * The method getChildFragmentManager() does not clear up
         * when the Fragment is detached.
         */
        if( fragment instanceof FileLoaderFragment ){
            fragment = reinstatiateFileLoaderFragment();
        }

        ft.replace(R.id.fragment_container, fragment);

    }

    @Override
    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        ft.remove(fragment);
    }

}


Answer 3:

可悲的是,它支持V4的一个bug,还有:(

当您选择通过抽屉式导航或其他类似的东西它的其他片段,其中有子片段的片段被分离。 因此,这些子片段fragmentManager(getChildFragmentManager())不再存在。 而那些片段返回,发生错误。 炸弹!

很显然,支持V4应清洁mChildFragmentManager在onDetach(),但它没有,所以我们必须依靠自己。 如以下在具有亚片段的片段代码:

@Override
    public void onDetach() {
        try {
            Field childFragmentManager = Fragment.class.getDeclaredField("mChildFragmentManager");
            childFragmentManager.setAccessible(true);
            childFragmentManager.set(this, null);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        super.onDetach();
    }

一切都会好的,有一个美好的一天:)



Answer 4:

可能你的错误是android.view.InflateException?

如果是的话,你应该动态地膨胀片段,不要使用XML布局。

并且,你不应该针对其定义XML布局到碎片的交易片段。



Answer 5:

我也有同样的问题。

一个活动,我有3个bouttons切换与transaction.replace片段(...)

FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.replace(R.id.layout_tablet_paneau, mLigneMessageFragment);

这其中一个片段包含有一个自定义FragmentPagerAdapter一个的ViewPage。 因此,我必须这样做getChildFragmentManager(),以alowed嵌套的片段。

构造函数是在这里:

public LignePagerAdapter(Fragment ligneMessageTabletFragment) {
        super(ligneMessageTabletFragment.getChildFragmentManager());
    }

所以,我有同样的错误:这个片段wrorks的首秀,但是当我告诉其他片段,回去就这一个,我得到这个异常:

02-26 11:57:50.798: D/ACRA(776): Wait for Toast + worker ended. Kill Application ? true
02-26 11:57:50.798: E/AndroidRuntime(776): FATAL EXCEPTION: main
02-26 11:57:50.798: E/AndroidRuntime(776): java.lang.IllegalStateException: No activity
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1075)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1070)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1861)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:1474)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:931)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1088)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1444)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:429)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.os.Handler.handleCallback(Handler.java:587)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.os.Handler.dispatchMessage(Handler.java:92)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.os.Looper.loop(Looper.java:132)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.app.ActivityThread.main(ActivityThread.java:4126)
02-26 11:57:50.798: E/AndroidRuntime(776):  at java.lang.reflect.Method.invokeNative(Native Method)
02-26 11:57:50.798: E/AndroidRuntime(776):  at java.lang.reflect.Method.invoke(Method.java:491)
02-26 11:57:50.798: E/AndroidRuntime(776):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:844)
02-26 11:57:50.798: E/AndroidRuntime(776):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
02-26 11:57:50.798: E/AndroidRuntime(776):  at dalvik.system.NativeStart.main(Native Method)
02-26 11:57:52.818: I/dalvikvm(776): threadid=4: reacting to signal 3
02-26 11:57:52.818: I/dalvikvm(776): Wrote stack traces to '/data/anr/traces.txt'

因此,与其把片段的同一个实例,我可以重新创建此所以解决这个问题,但我似乎效率不高。

transaction.replace(R.id.layout_tablet_paneau, LigneMessageTabletFragment.newInstance());


Answer 6:

请参阅@lopisan答案:

我用他的很长一段时间的解决方案。

但我找出有更好的办法来做到这一点!

如果mChildFragmentManager.mActivity为空,然后设置mChildFragmentManager为null。 当performActivityCreated方法。

@Override
void performActivityCreated(Bundle savedInstanceState) {
    if (getFragmentManagerActivity(mChildFragmentManager) == null) {
        setChildFragmentManager(this, null);
    }
    super.performActivityCreated(savedInstanceState);
}


public static FragmentActivity getFragmentManagerActivity(FragmentManager fragmentManager) {
    FragmentManagerImpl fm = (FragmentManagerImpl) fragmentManager;
    return fm.mActivity;
}



private static final Field sChildFragmentManagerField;
static {
    /**
     * BUG : causing a java.IllegalStateException error, No Activity, only
     * when navigating to Fragment for the SECOND time
     * http://stackoverflow.com /questions/15207305/getting-the-error-java-lang-illegalstateexception-activity-has-been-destroyed
     * http://stackoverflow.com/questions/14929907/causing-a-java-illegalstateexception-error-no-activity-only-when-navigating-to
     */
    Field f = null;
    try {
        f = Fragment.class.getDeclaredField("mChildFragmentManager");
        f.setAccessible(true);
    } catch (NoSuchFieldException e) {
        Log.e(TAG, "Error getting mChildFragmentManager field", e);
    }
    sChildFragmentManagerField = f;
}

public static void setChildFragmentManager(Fragment fragment, FragmentManager fragmentManager) {
    if (sChildFragmentManagerField != null) {
        try {
            sChildFragmentManagerField.set(fragment, fragmentManager);
        } catch (Exception e) {
            Log.e(TAG, "Error setting mChildFragmentManager field", e);
        }
    }
}


Answer 7:

我坚持使用BottomNavigationView开关和更换导致应用程序崩溃片段的相同错误。 以一般速度是工作完全正常,如果用户做快速切换它使用的崩溃说

IllegalStateException异常无活动

在日志

之前,我有

fragmentA = new FragmentA();
fragmentB = new FragmentB();
fragmentC = new FragmentC();

mBottomNavigationView.setOnNavigationItemSelectedListener(item -> {
        switch (item.getItemId()) {
   case R.id.fragmentA:
         replaceFragment(fragmentA);
   case R.id.fragmentB:
        repalceFragment(fragmentB);
   case R.id.fragmentC:
        repalceFragment(fragmentC);
   }
};

我觉得这个预创建片段并利用它们是为替换正在创建的问题,现在我把它重新创建每次。 它开始工作的罚款

mBottomNavigationView.setOnNavigationItemSelectedListener(item -> {
        switch (item.getItemId()) {
   case R.id.fragmentA:
        fragment = new FragmentA();
         replaceFragment(fragment);
   case R.id.fragmentB:
        fragment = new FragmentB();
        repalceFragment(fragment);
   case R.id.fragmentC:
        fragment = new FragmentC();
        repalceFragment(fragment);
   }
};

 public void repalceFragment(Fragment fragment) {
    if (!this.isFinishing()) {
        if (!fragment.isAdded()) {
            if (!this.mDisplayedFragment.isRemoving()) {
                getFragmentManager().beginTransaction().replace(R.id.layout_fragment_container, fragment).commit();
                this.mDisplayedFragment = fragment;
            }
        }
    }
}

希望它的一些有用的,我没有太多的防御性编码,但它解决了我的片段的快速切换问题



Answer 8:

请检查该链接的号码32:

儿童FragmentManager保留母公司分离后的片段

脚步:

  1. 下载这个类复制到项目
  2. 扩展的每个片段的支持V4一个(最佳实践)
  3. 使用类代替FragmentStatePagerAdapter


文章来源: causing a java.IllegalStateException error, No Activity, only when navigating to Fragment for the SECOND time