Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
IllegalStateException:已添加片段-在Android OS 4.3上启动应用程序期间_Android_Android Fragments_Android Viewpager_Fragmenttransaction_Fragmentstatepageradapter - Fatal编程技术网

IllegalStateException:已添加片段-在Android OS 4.3上启动应用程序期间

IllegalStateException:已添加片段-在Android OS 4.3上启动应用程序期间,android,android-fragments,android-viewpager,fragmenttransaction,fragmentstatepageradapter,Android,Android Fragments,Android Viewpager,Fragmenttransaction,Fragmentstatepageradapter,我的Android应用程序只有一个活动,其中一个选项卡控制器承载4个选项卡——每个选项卡由一个片段表示。当我在运行OS 4.03的测试设备上运行该应用程序时,该应用程序可以工作,我可以导航到不同的选项卡等。当该应用程序在运行OS 4.3的设备上运行时,该应用程序在启动过程中崩溃,并添加了一个IllegalStateException:Fragment:MyFirstTabFragment 以下是堆栈跟踪: java.lang.IllegalStateException:已添加片段:MyFirst

我的Android应用程序只有一个活动,其中一个选项卡控制器承载4个选项卡——每个选项卡由一个片段表示。当我在运行OS 4.03的测试设备上运行该应用程序时,该应用程序可以工作,我可以导航到不同的选项卡等。当该应用程序在运行OS 4.3的设备上运行时,该应用程序在启动过程中崩溃,并添加了一个IllegalStateException:Fragment:MyFirstTabFragment

以下是堆栈跟踪:


java.lang.IllegalStateException:已添加片段:MyFirstTabFragment{41866dc0#0 id=0x7f080000 MyFirstTabFragment} 在android.app.FragmentManagerImpl.addFragment(FragmentManager.java:1128) 运行(BackStackRecord.java:616) 位于android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1435) 在android.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:474) 位于android.support.v13.app.FragmentStatePagerAdapter.finishUpdate(FragmentStatePagerAdapter.java:167) 位于android.support.v4.view.ViewPager.populate(ViewPager.java:1068) 在android.support.v4.view.ViewPager.populate(ViewPager.java:914) 在android.support.v4.view.ViewPager.onMeasure上(ViewPager.java:1436) 在android.view.view.measure上(view.java:15848) 位于android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5012) 位于android.widget.FrameLayout.onMeasure(FrameLayout.java:310) 在android.view.view.measure上(view.java:15848) 位于android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5012) 位于com.android.internal.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:302) 在android.view.view.measure上(view.java:15848) 位于android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5012) 位于android.widget.FrameLayout.onMeasure(FrameLayout.java:310) 在com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure上(PhoneWindow.java:2189) 在android.view.view.measure上(view.java:15848) 在android.view.ViewRootImpl.performMeasure上(ViewRootImpl.java:1905) 在android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1104) 在android.view.ViewRootImpl.performTraversals上(ViewRootImpl.java:1284) 位于android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1004) 在android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5481) 在android.view.Choreographer$CallbackRecord.run(Choreographer.java:749) 位于android.view.Choreographer.doCallbacks(Choreographer.java:562) 位于android.view.Choreographer.doFrame(Choreographer.java:532) 在android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:735)中 位于android.os.Handler.handleCallback(Handler.java:730) 位于android.os.Handler.dispatchMessage(Handler.java:92) 位于android.os.Looper.loop(Looper.java:137) 位于android.app.ActivityThread.main(ActivityThread.java:5103) 位于java.lang.reflect.Method.Invokenactive(本机方法) 位于java.lang.reflect.Method.invoke(Method.java:525) 在com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run上(ZygoteInit.java:737) 位于com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 在dalvik.system.NativeStart.main(本机方法)

该问题似乎是由于尝试在FragmentStatePagerAdapter扩展类的getItem()方法中的FragmentTransaction中添加片段引起的,如下所示:

public class MyFragmentStatePagerAdapter extends android.support.v13.app.FragmentStatePagerAdapter {        

    @Override
    public Fragment getItem(int position) {
        if (position == 0) {
            Fragment fragment = new MyFirstTabFragment();
            getFragmentManager().beginTransaction().add(fragment, "MyFirstTabFragmentTag").commit();

         // getFragmentManager().beginTransaction().replace(R.id.pager, fragment, "MyFirstTabFragmentTag").commit();

            return fragment;  
        } else if (position == 1) {
            Fragment fragment = new MySecondTabFragment();
            getFragmentManager().beginTransaction().add(fragment, "MySecondTabFragmentTag").commit();

         // getFragmentManager().beginTransaction().replace(R.id.pager, fragment, "MySecondTabFragmentTag").commit();

            return fragment;  
        }
    }
.
.
.

}
我调用add()的原因是,我可以将标记与片段相关联,以便在选择/取消选择选项卡时访问这些片段,在这些片段实例上调用方法

我搜索了有关IllegalStateException的各种帖子,并尝试了各种建议,包括调用replace()而不是add(),调用remove()然后add(),调用MyFirstTabFragment.instantiate()而不是new MyFirstTabFragment(),这些更改都没有纠正问题

我怀疑我可能在这个过程中过早地执行了这个FragmentTransaction,因为当我尝试添加片段或用我的标记替换片段时,ViewPager当前正在添加片段。有人对这个过程有更好的见解吗?有没有更好的地方可以进行这些单独的add()调用来标记我的片段


提前感谢您的建议

只需返回适配器的
getItem
中的片段,当您调用
setAdapter
时,它将由viewpager自己添加到屏幕中

@Override
public Fragment getItem(int position) {
    if (position == 0) {
        Fragment fragment = new MyFirstTabFragment();

        return fragment;  
    } else if (position == 1) {
        Fragment fragment = new MySecondTabFragment();

        return fragment;  
    }
}

所以只要完成这个线程

我删除了适配器的getItem()方法中的add()或replace()调用,只是实例化新片段以避免IllegalStateException,但无法确定移动replace()调用的逻辑位置,以便标记片段。这是不幸的,因为使用标签将是最可靠的解决方案

我尝试使用内部的“android:switcher…”标记访问片段,但这似乎不起作用-查看我片段的标记,标记总是空的-因此可能他们更改了内部行为,默认情况下不再生成标记


我已经求助于维护我自己的片段实例集合,这些片段实例是我在getItem()调用期间填充的,在适配器的destroyItem()调用期间更新的。我希望在此过程中不会出现意外情况,这将导致我的集合中的实例与ViewPager/适配器存储的实例不同

你本可以这样做的:

private Fragment[] pages = new Fragment[2];

@Override
public Fragment getItem(int position) {

     if(pages[position] == null){

        switch(position){

        case 0:
           pages[position] = new MyFirstTabFragment();
        break;

        case 1:
            pages[position] = new MySecondTabFragment();
        break:

        default:
        //you have to determine a default position
        break;
    }
  }

  return pages[position];
}

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    super.destroyItem(container, position, object);
    pages[position] = null;
}
因此,您可以访问适配器片段实例,只需调用:

MyFirstTabFragment firstFragment = (MyFirstTabFragment)adapter.getItem(0);
它不会为通知的职位创建另一个实例

这对我们有用:

private FragmentManager fm;
private Map<Integer, Fragment> map;

@Override
public Fragment getItem(int position) {
    fm.executePendingTransactions();
    if (map == null)
        map = new HashMap<>();

    if (map.containsKey(position))
        return map.get(position);

    Fragment fragment = new Fragment();
    ...
    map.put(position, fragment);
    return fragment;
}
私有碎片管理器fm;
私人地图;
@凌驾
公共片段getItem(int位置){
fm.executePendingTransactions();
if(map==null)
地图=新的