Java 在已经运行的Android ViewPager中插入新片段

Java 在已经运行的Android ViewPager中插入新片段,java,android,android-fragments,Java,Android,Android Fragments,尝试在Android ViewPager中向不同页面动态添加片段 动态地将片段添加到片段列表的末尾可以正常工作,但尝试添加到下一个插槽(当前可查看页面之后的未查看页面)。我已经尝试添加到片段的arraylist中,使用notifyDataSetChanged并尝试在每个片段上使用set,然后将每个片段设置为上一项 编辑:更新代码 class MainPagerAdapter extends FragmentPagerAdapter { public MainPagerAdapter(F

尝试在Android ViewPager中向不同页面动态添加片段

动态地将片段添加到片段列表的末尾可以正常工作,但尝试添加到下一个插槽(当前可查看页面之后的未查看页面)。我已经尝试添加到片段的arraylist中,使用notifyDataSetChanged并尝试在每个片段上使用set,然后将每个片段设置为上一项

编辑:更新代码

class MainPagerAdapter extends FragmentPagerAdapter {

    public MainPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public PageFragment getItem(int position) {
        return PageFragment.newInstance(Datamart.getInstance().getURLs().get(position));
    }

    @Override
    public int getCount() {
        return Datamart.getInstance().getURLs().size();
    }

    @Override
    public int getItemPosition(Object object) {
        PageFragment pageFragment = (PageFragment) object;
        for ( int i = 0; i < getCount(); i++ ) {
            if ( pageFragment.getURL().equals( Datamart.getInstance().getURLs().get(i) ) ) {
                return i;
            }
        }
        return POSITION_NONE;
    }
}
class MainPagerAdapter扩展了FragmentPagerAdapter{
公共主页RADAPTER(碎片管理器fm){
超级(fm);
}
@凌驾
公共页面片段getItem(int位置){
返回PageFragment.newInstance(Datamart.getInstance().getURLs().get(position));
}
@凌驾
public int getCount(){
返回Datamart.getInstance().getURLs().size();
}
@凌驾
public int getItemPosition(对象){
PageFragment=(PageFragment)对象;
对于(int i=0;i
在数据集市中:

public class Datamart {

    static Datamart instance;

    private ArrayList<String> URLs;
    private MainPagerAdapter mainPagerAdapter;
    private ViewPager viewPager;

    public Datamart() {
        URLs = new ArrayList<>();
    }

    public static Datamart getInstance() {
        if (instance == null) {
            instance = new Datamart();
        }
        return instance;
    }

    public MainPagerAdapter getMainPagerAdapter() {
        return mainPagerAdapter;
    }

    public void setMainPagerAdapter(MainPagerAdapter mainPagerAdapter) {
        this.mainPagerAdapter = mainPagerAdapter;
    }

    public ViewPager getViewPager() {
        return viewPager;
    }

    public void setViewPager(ViewPager viewPager) {
        this.viewPager = viewPager;
    }

    public void addToEnd( String URL ) {
        URLs.add(URL);
        mainPagerAdapter.notifyDataSetChanged();
    }

    public void addNext( String URL ) {
        URLs.add(viewPager.getCurrentItem() + 1, URL);
        mainPagerAdapter.notifyDataSetChanged();
    }

    public ArrayList<String> getURLs() {
        return URLs;
    }

    public void setURLs(ArrayList<String> URLs) {
        this.URLs = URLs;
    }
}
公共类数据集市{
静态数据集市实例;
私有ArrayList URL;
专用主页面播放机主页面播放机;
私人视页机视页机;
公共数据集市(){
URL=新的ArrayList();
}
公共静态数据集市getInstance(){
if(实例==null){
实例=新数据集市();
}
返回实例;
}
公共MainPagerAdapter getMainPagerAdapter(){
返回mainPagerAdapter;
}
公共无效设置MainPagerAdapter(MainPagerAdapter MainPagerAdapter){
this.mainPagerAdapter=mainPagerAdapter;
}
公共ViewPager getViewPager(){
返回寻呼机;
}
公共无效设置ViewPager(ViewPager ViewPager){
this.viewPager=viewPager;
}
公共void addToEnd(字符串URL){
添加(URL);
mainPagerAdapter.notifyDataSetChanged();
}
公共void addNext(字符串URL){
添加(viewPager.getCurrentItem()+1,URL);
mainPagerAdapter.notifyDataSetChanged();
}
公共ArrayList getURLs(){
返回URL;
}
公共无效设置URL(ArrayList URL){
this.url=url;
}
}

<代码> < p> <代码> ViewPager <代码>正在尽最大努力来跟踪所有片段的去向,而你把它弄糊涂了,因为你在中间插入了一个片段而不告诉它。

让我们做一个例子。假设您有两个页面,以便显示第一个页面,第二个页面是右侧的屏幕外页面。第一页有
fragment0
,第二页有
fragment1

首先,请记住,由于
ViewPager
正在管理屏幕外的页面,它已经认为它知道第二个页面片段是什么,即
fragment1

在现有页面片段之间插入片段时,
ViewPager
不会立即询问第二个位置的片段,而是询问第二个位置的片段是否已更改

这就是
getItemPosition()
的作用。您没有在
FragmentPagerAdapter
中实现
getItemPosition()
,因此
getItemPosition()
的默认行为是返回
POSITION\u UNCHANGED
。(正如您将看到的,这就是为什么在末尾添加片段不会导致错误的原因。)

因此,当您调用
notifyDataSetChanged()
时,
ViewPager
调用了
getCount()
并看到现在有三个页面,而不是两个页面。然后,它为第0页和第1页(它知道的页面)调用了
getItemPosition()
,默认实现告诉它没有任何更改

<>但是有些事情发生了变化,你在两个现有页面中间插入了一个页面/片段。code>ViewPager
询问您第二页是否已更改,您的
getItemPosition()
应该返回
2
,而不是
POSITION\u未更改

现在,因为您的
getCount()
返回了
3
而不是
2
ViewPager
知道末尾有一个它不知道的新页面,所以它调用
getItem()
来获取新片段

这里是发生错误的地方。您的
getItem()
方法返回了第3页的
fragment1
,并且
ViewPager
阻塞了,因为您将它已经知道的片段交给了它。具体来说,它使用片段的标记进行一些整理。它会创建一个标记,标记出页面的容器id和项目位置(页码)。因此,在任何给定的时间,它期望(a)标记为null,或者(b)标记将是它已经从容器id和项目位置计算出的相同值。这两个条件都不是真的,因此引发了
IllegalStateException

那么你如何解决这个问题呢

您实现了一个执行正确操作的
getItemPosition()
。调用
getItemPosition()
时,扫描片段列表,找到匹配片段时,返回片段的索引。如果删除的片段在列表中没有匹配的片段,则返回
POSITION\u NONE
,告知
ViewPager
页面应被删除
ViewPager
然后将调用您的
getItem()
方法来获取新页面。这样,
ViewPager
就可以始终与适配器保持同步


当我编写一个
FragmentPagerAdapter
时,我甚至不使用