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