Android的嵌套片段问题和QUOT; java.lang.IllegalStateException:活动已被破坏" [英] Android Nested Fragments Issue "java.lang.IllegalStateException: Activity has been destroyed"

查看:101
本文介绍了Android的嵌套片段问题和QUOT; java.lang.IllegalStateException:活动已被破坏"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

正如你可能知道Android支持嵌套的片段,也可以通过与空气污染指数17,所以基本上我想添加嵌套碎片进入ViewPager的片段之一,并熟悉这一新的很好的功能支持库。

一切都将按预期在第一个应用程序启动即我可以添加子片段,浏览那些片段,手柄后面的堆栈等。

但问题是,当我离开通过单击后退按钮,并重新启动应用程序的应用程序,我得到了以下异常大部分时间里,并不总是:

  java.lang.IllegalStateException:活动已被破坏
    在android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1342)
    在android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595)
    在android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574)
    在com.cnlms.andnestedfragments.ui.fragments.FragWrapper.addChildFragment(FragWrapper.java:145)
    在com.cnlms.andnestedfragments.ui.fragments.FragWrapper.onActivityCreated(FragWrapper.java:96)
    在android.support.v4.app.Fragment.performActivityCreated(Fragment.java:1468)
    在android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:931)
    在android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1088)
    在android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
    在android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1444)
    在android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:461)
    在android.support.v4.app.FragmentStatePagerAdapter.finishUpdate(FragmentStatePagerAdapter.java:163)
    在android.support.v4.view.ViewPager.populate(ViewPager.java:1012)
    在android.support.v4.view.ViewPager.populate(ViewPager.java:881)
    在android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1366)
    在android.view.View.measure(View.java:15172)
    在android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4814)
    在android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
    在android.view.View.measure(View.java:15172)
    在android.widget.LinearLayout.measureVertical(LinearLayout.java:833)
    在android.widget.LinearLayout.onMeasure(LinearLayout.java:574)
    在android.view.View.measure(View.java:15172)
    在android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4814)
    在android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
    在com.android.internal.policy.impl.PhoneWindow $ DecorView.onMeasure(PhoneWindow.java:2148)
    在android.view.View.measure(View.java:15172)
    在android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:1848)
    在android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1100)
    在android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1273)
    在android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:998)
    在android.view.ViewRootImpl $ TraversalRunnable.run(ViewRootImpl.java:4212)
    在android.view.Choreographer $ CallbackRecord.run(Choreographer.java:725)
    在android.view.Choreographer.doCallbacks(Choreographer.java:555)
    在android.view.Choreographer.doFrame(Choreographer.java:525)
    在android.view.Choreographer $ FrameDisplayEventReceiver.run(Choreographer.java:711)
    在android.os.Handler.handleCallback(Handler.java:615)
    在android.os.Handler.dispatchMessage(Handler.java:92)
    在android.os.Looper.loop(Looper.java:137)
    在android.app.ActivityThread.main(ActivityThread.java:4745)
    在java.lang.reflect.Method.invokeNative(本机方法)
    在java.lang.reflect.Method.invoke(Method.java:511)
    在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:786)
    在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
    在dalvik.system.NativeStart.main(本机方法)
 

整个项目可这里

可以活动为null在某些时候?我的意思是当我打电话getChildFragmentManager(),应该不是活动连接到段管理器?任何建议将大大AP preciated。

在应用程序的更多细节,

ViewPager举办两个碎片实例:FragRegular和FragWrapper。第一个是只是一个简单的无用的片段;第二个,FragWrapper,充当一个父片段即容器为子片段。下面是FragWrapper的布局是这样的:

 < XML版本=1.0编码=UTF-8&GT?;
< RelativeLayout的
    的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
    机器人:layout_width =match_parent
    机器人:layout_height =match_parent
    机器人:方向=垂直>

    <! - 
        点击后添加嵌套子片段
     - >
    <按钮
        机器人:ID =@ + ID / btn_go_deep
        机器人:layout_width =match_parent
        机器人:layout_height =WRAP_CONTENT
        机器人:layout_alignParentBottom =真
        机器人:文本=!转到Nesty/>

    <! - 
        嵌套片段集装箱
     - >
    <的FrameLayout
        机器人:ID =@ + ID / frag_container
        机器人:方向=垂直
        机器人:layout_width =FILL_PARENT
        机器人:layout_height =match_parent
        机器人:layout_above =@ ID / btn_go_deep/>

< / RelativeLayout的>
 

因此​​,基本上在第一子片段加入到FragWrapper的onActivityCreated()回调方法内FragWrapper,以及随后的子片段在运行时添加,一个按钮点击触发。下面是FragWrapper类是这样的:

 公开最后一类FragWrapper扩展BaseFragment {
    / **
     *
     *承载嵌套子片段包装片段。
     *
     *第一个孩子片段在onActivityCreated加()回调
     *
     *更多的孩子碎片可以在运行时增加点击'去Nesty!
     *按钮。
     *
    * /

    / **
     *阻碍了叠片段标签
     * /
    私人堆叠式和LT;字符串> backStack;

    / **
     *儿童碎片经理
     * /
    私人FragmentManager FM;

    / **
     *片段标签
     * /
    私人诠释fragCount = 1;


    私有静态FragWrapper实例;

    公共静态FragWrapper的getInstance(){

        如果(例如== NULL){

            例如=新FragWrapper();

        }

        返回实例;

    }

    @覆盖
    公共查看onCreateView(LayoutInflater充气,容器的ViewGroup,捆绑savedInstanceState){

        查看查看= inflater.inflate(R.layout.frag_wrapper,集装箱,假);

        view.findViewById(R.id.btn_go_deep).setOnClickListener(新View.OnClickListener(){

            @覆盖
            公共无效的onClick(视图v){

                / **
                 *添加嵌套子片段
                 * /
                fragCount + = 1;

                addChildFragment(
                        FragChild.newInstance(fragCount)
                        将String.valueOf(fragCount)
                        真正
                );
            }

        });

        返回查看;
    }

    @覆盖
    公共无效onActivityCreated(包savedInstanceState){

        super.onActivityCreated(savedInstanceState);

        / **
         *添加初始片段
         * /
        addChildFragment(
                FragChild.newInstance(fragCount)
                将String.valueOf(fragCount)
                假
        );

    }

    私人无效addChildFragment(最后片段的片段,最后弦乐fragmentTag,最后布尔addToBackStack){

        / **
         *初始化子片段经理
         * /
        如果(FM == NULL)FM = getChildFragmentManager();


        / **
          *开始一个新的事务
         * /
        FragmentTransaction英尺= fm.beginTransaction();


        / **
         *隐藏最后添加片段
         * /
        如果(backStack =空&安培;!&安培;!backStack.isEmpty()){

            ft.hide(fm.findFragmentByTag(backStack.peek()));

        }

        / **
         *添加新的片段
         * /
        ft.add(R.id.frag_container,片段,fragmentTag);


        / **
         *添加到后退堆栈
         * /
         如果(addToBackStack){

            ft.addToBackStack(空);

        }

         / **
         *提交交易
         * /
        ft.commit();


        / **
         *保存片段标记
         * /
        如果(backStack == NULL)backStack =新的堆栈<字符串>();

            backStack.push(fragmentTag);

    }

    公共布尔popFragment(){

        / **
         *允许此片段消耗后退按钮点击
        * /
        如果(backStack =空&安培;!&安培;!backStack.isEmpty()){

            backStack.pop();

            fragCount- = 1;

        }

        返回FM = NULL和放大器;!&安培; fm.popBackStackImmediate();

    }

    @覆盖
    公共布尔回pressed(){

        返回popFragment();

    }
}
 

解决方案

有人张贴另一个问题相似,这个问题是由于在ChildFragmentManager的错误。基本上,孩子FragmentManager结束与一个破碎内部状态时,它是从该活动分离。有一个在这里原来答案

As you might know Android supports Nested Fragments, also via support library with API level 17. So basically I'm trying to add nested fragments into one of the ViewPager's fragments and get familiar with this new nice feature.

Everything works as expected at the first app launch i.e I can add child fragments, navigate through those fragments, handle the back stack etc..

But the problem is that when I leave the app by clicking Back button and relaunch the app, I got the following exception most of the time, not always :

java.lang.IllegalStateException: Activity has been destroyed
    at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1342)
    at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595)
    at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574)
    at com.cnlms.andnestedfragments.ui.fragments.FragWrapper.addChildFragment(FragWrapper.java:145)
    at com.cnlms.andnestedfragments.ui.fragments.FragWrapper.onActivityCreated(FragWrapper.java:96)
    at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:1468)
    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:931)
    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1088)
    at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
    at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1444)
    at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:461)
    at android.support.v4.app.FragmentStatePagerAdapter.finishUpdate(FragmentStatePagerAdapter.java:163)
    at android.support.v4.view.ViewPager.populate(ViewPager.java:1012)
    at android.support.v4.view.ViewPager.populate(ViewPager.java:881)
    at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1366)
    at android.view.View.measure(View.java:15172)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4814)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
    at android.view.View.measure(View.java:15172)
    at android.widget.LinearLayout.measureVertical(LinearLayout.java:833)
    at android.widget.LinearLayout.onMeasure(LinearLayout.java:574)
    at android.view.View.measure(View.java:15172)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4814)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
    at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2148)
    at android.view.View.measure(View.java:15172)
    at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:1848)
    at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1100)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1273)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:998)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4212)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
    at android.view.Choreographer.doCallbacks(Choreographer.java:555)
    at android.view.Choreographer.doFrame(Choreographer.java:525)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
    at android.os.Handler.handleCallback(Handler.java:615)
    at android.os.Handler.dispatchMessage(Handler.java:92)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:4745)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
    at dalvik.system.NativeStart.main(Native Method)

The whole project is available here.

Can the activity be null at some point? I mean when I call getChildFragmentManager(), shouldn't the activity be attached to the Fragment Manager? Any suggestion will be greatly appreciated.

More details on the app,

ViewPager hosts two fragment instances: FragRegular and FragWrapper. First one is just a simple useless fragment; the second one, FragWrapper, acts as a parent fragment i.e the container for the child fragments. Here's what FragWrapper's layout looks like:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <!--
        Adds nested child fragments when clicked
    -->
    <Button
        android:id="@+id/btn_go_deep"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:text="Go Nesty!"/>

    <!--
        Nested Fragment Container
    -->
    <FrameLayout
        android:id="@+id/frag_container"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="match_parent"
        android:layout_above="@id/btn_go_deep"/>

</RelativeLayout>

So basically the first child fragment is added into FragWrapper within the onActivityCreated() callback method of the FragWrapper, and the subsequent child fragments are added at runtime, triggered with a button click. Here's what FragWrapper class looks like:

public final class FragWrapper extends BaseFragment {
    /**
     *
     *  The Wrapper Fragment that hosts nested child fragments.
     *
     *  First child fragment is added in onActivityCreated() callback
     *
     *  More child fragments can be added at runtime by clicking 'Go Nesty!'
     *  button.
     *
    */

    /**
     *  Holds back stacked fragment tags
     */
    private Stack<String> backStack;

    /**
     *  Child Fragment Manager
     */
    private FragmentManager fm;

    /**
     *  Fragment Tags
     */
    private int fragCount = 1;


    private static FragWrapper instance;

    public static FragWrapper getInstance() {

        if (instance == null) {

            instance = new FragWrapper();

        }

        return instance;

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.frag_wrapper, container, false);

        view.findViewById(R.id.btn_go_deep).setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

                /**
                 *  Adds nested child fragments
                 */
                fragCount+=1;

                addChildFragment(
                        FragChild.newInstance(fragCount),
                        String.valueOf(fragCount),
                        true
                );
            }

        });

        return view;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {

        super.onActivityCreated(savedInstanceState);

        /**
         *  Add Initial Fragment
         */
        addChildFragment(
                FragChild.newInstance(fragCount),
                String.valueOf(fragCount),
                false
        );

    }

    private void addChildFragment(final Fragment fragment, final String fragmentTag, final boolean addToBackStack) {

        /**
         *  initialize child fragment manager
         */
        if (fm == null) fm = getChildFragmentManager();


        /**
          *  Starts a new transaction
         */
        FragmentTransaction ft = fm.beginTransaction();


        /** 
         *  Hide lastly added fragment
         */
        if (backStack != null  && !backStack.isEmpty()) {

            ft.hide(fm.findFragmentByTag(backStack.peek()));

        }

        /** 
         *  Add new fragment
         */
        ft.add(R.id.frag_container, fragment, fragmentTag );


        /**
         *  Add to back stack
         */
         if (addToBackStack) {

            ft.addToBackStack(null);

        }

         /**
         *  Commit transaction
         */
        ft.commit();


        /**
         * Save fragment tag
         */
        if (backStack == null) backStack = new Stack<String>();

            backStack.push(fragmentTag);

    }

    public boolean popFragment() {

        /**
         *  Allow this fragment to consume the back button click
        */
        if (backStack != null   && !backStack.isEmpty()) {

            backStack.pop();

            fragCount-=1;

        }

        return fm != null && fm.popBackStackImmediate();

    }

    @Override
    public boolean backPressed() {

        return popFragment();

    }
}

解决方案

Someone posted another question similar and the problem is due to a bug in the ChildFragmentManager. Basically, the child FragmentManager ends up with a broken internal state when it is detached from the activity. Have a look at the original answer here

这篇关于Android的嵌套片段问题和QUOT; java.lang.IllegalStateException:活动已被破坏&QUOT;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆