在调用getChildFragmentManager()之后调用getSupportFragmentManager()会导致IllegalStateException: Recursive entry to executePendingTransactions。

3
我正在使用FrameLayout来显示片段。
 <FrameLayout
        android:id="@+id/fragment_content"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_above="@+id/bottom_layout"
        android:background="@android:color/white" >
    </FrameLayout>

我使用以下代码打开片段:
ft.add(R.id.fragment_content, frag);
ft.commit();
fm.beginTransaction();

一个片段包含地图,因此我在布局文件中使用以下行:
<fragment
        android:id="@+id/trafic_Alarm_main_mapView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        class="com.Utilities.MySupportMapFragment"
        android:layout_alignParentTop="true" />

这是我的Java代码

try{
mMap=(MySupportMapFragment)TabsActivity.fm.findFragmentById(R.id.trafic_Alarm_main_mapView)).getMap();
}catch (Exception e){
mMap=((MySupportMapFragment)getChildFragmentManager().findFragmentById(R.id.trafic_Alarm_main_mapView)).getMap();
}

现在,如果调用getChildFragmentManager()并切换到另一个使用getSupportFragmentManager开始事务的片段会导致崩溃。以下是日志记录:
01-16 18:36:15.690    7294-7294/com.TrafikAlarm E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.TrafikAlarm, PID: 7294
    java.lang.IllegalStateException: Recursive entry to executePendingTransactions
            at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1461)
            at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:454)
            at android.os.Handler.handleCallback(Handler.java:739)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5221)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

我正在使用Android Studio编译这些库,

compile 'com.google.android.gms:play-services:6.5.87'
compile 'com.android.support:appcompat-v7:21.0.3'

当我使用Eclipse时,我不需要使用getChildFragmentManager,一切都很正常。
提前感谢。

那段Java代码的上下文是什么?它在哪里?我猜是在父Fragment中吧? - Andy
你可能正在尝试使用嵌套在其他片段中的片段。请参考此链接https://dev59.com/eOo6XIcBkEYKwwoYKQ_G。 - Krish
安迪,上下文是片段活动类。 - Jan
1
你为什么要第二次调用 fm.beginTransaction(); - matiash
抱歉,我的代码中没有两次调用开始事务,我已编辑了我的问题。 - Jan
显示剩余4条评论
5个回答

1

你好,看起来你遇到了递归问题 Recursive entry to executePendingTransactions,因为你重复调用了该函数,并且在异常处理中尝试捕获异常错误并尝试“做一些事情()”,这是错误的惯例。

try{

mMap=(MySupportMapFragment)TabsActivity.fm.findFragmentById(R.id.trafic_Alarm_main_mapView)).getMap();

}catch (Exception e){

mMap=((MySupportMapFragment)getChildFragmentManager().findFragmentById(R.id.trafic_Alarm_main_mapView)).getMap();

}

移除在 catch 区域不必要的调用,如果出现新错误,请确保阅读日志记录,并在正确的 @override 中进行片段的添加/删除,例如与 fragment 一起工作的您的活动中的 @onCreate

希望对您有所帮助。


1

由于您的上下文是一个片段,您是否尝试在使用它之前调用子片段管理器上的super方法?

super(fragment.getChildFragmentManager());


我应该在哪里调用它? - Jan
在此方法中的第一行:try{ mMap=(MySupportMapFragment)TabsActivity.fm.findFragmentById(R.id.trafic_Alarm_main_mapView)).getMap(); }catch (Exception e){ mMap=((MySupportMapFragment)getChildFragmentManager().findFragmentById(R.id.trafic_Alarm_main_mapView)).getMap(); } - Marcin D
我没有在任何重写的方法中使用它。父类重写的方法是onCreateView,它不支持super(fragment.getChildFragmentManager()); - Jan

1
  1. 当布局包含一个Fragment时,您无法将布局膨胀到Fragment中。嵌套的Fragment只支持动态添加。
  2. FILL_PARENT(API Level 8及更高版本中已更名为MATCH_PARENT)。

我尝试使用这个代码,但是出现了相同的错误: mMap=((MySupportMapFragment)getParentFragment().getFragmentManager().findFragmentById(R.id.trafic_Alarm_main_mapView)).getMap();java.lang.NullPointerException: 尝试在一个null对象上调用虚拟方法'android.support.v4.app.FragmentManager android.support.v4.app.Fragment.getFragmentManager()' - Jan

0

布局片段非常适合一次性的添加和忘记使用。除此之外,您必须使用Java代码来管理片段。

在添加、替换片段时,只需遵循一些规则即可:

Int frameId = // id of host view
Fragment manager = // fragment manager, of Activity or a Fragment
String tag = // unique tag for the fragment
String clazz = // class name of the fragment
Bundle args = // initial data to be supplied to fragment instance

Fragment frg = manager.findFragmentbyTag(tag);

if(frg == null){
  frg = Fragment.instantiate(context,clazz,args);
}

if(!frg.isAdded()){
   manager.beginTransaction().add(frameId, frg, tag).commit();
}

如果一个Fragment在启动时还要显示一个嵌套的Fragment,可以在其onViewCreated()中使用上述代码。
FragmentManager的性质是异步的,在commit()之后,它不会立即应用Fragment的更改。提交被安排在未来的某个时间进行。虽然executePendingTransactions()可用,但应该非常小心地使用。它会立即运行所有已安排的事务,并且当它们正在运行时,您不能再次调用此函数。

0

我已经找到了这个错误。我使用FragmentActivity管理器返回地图对象以删除导致问题的地图片段,而日志没有显示任何问题。因此,我进行了更改。

TabsActivity.fm.beginTransaction().remove((MySupportMapFragment) TabsActivity.fm.findFragmentById(R.id.trafic_Alarm_main_mapView)).commit();

TabsActivity.fm.beginTransaction().remove((MySupportMapFragment) getChildFragmentManager().findFragmentById(R.id.trafic_Alarm_main_mapView)).commit();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接