我使用FragmentStatePagerAdapter
来显示ViewPager中的片段,所有这些片段都遵循相同的布局容器(FrameLayout
),但它的数字是可更改的在运行时,我将它们全部放入静态List
片段中并将该列表传递给FragmentStatePagerAdapter
(第一次通过它的构造函数,每次之后我只是更新列表和notifydatasetchanged
):
public class MyPageAdapter extends FragmentStatePagerAdapter {
public static List<Fragment> myFragments = new ArrayList<Fragment>();
public MyPageAdapter(FragmentManager fragmentManager, List<Fragment> fragments) {
super(fragmentManager);
myFragments = fragments;
}
public Fragment getItem(int i) {
return myFragments.get(i);
}
@Override
public int getCount() {
return myFragments.size();
}
}
现在,这是我在运行时通过以下方式创建Fragment List
的方式:
public List<Fragment> fragmenting(int num) { // num: the Number of fragments i wanna create
List<Fragment> fragments = new Vector<Fragment>();
for(int i =0; i < num ; i++){
Bundle page = new Bundle();
page.putInt("index", i);
fragments.add(Fragment.instantiate(mContext, MyFragment.class.getName(), page));
}
return fragments;
}
并提交新的片段到ViewPager
:
public static PagerAdapter ad;
public static ViewPager sViewPager;
private static MyPageAdapter mpa;
public void display_fragments(int i, boolean init) {
if(init){ // init means we are in the first initialization and it goes here only at the first time
List<Fragment> fragments = fragmenting(i);
mpa = new MyPageAdapter(getChildFragmentManager(), fragments);
sViewPager = (ViewPager) view.findViewById(R.id.my_view_pager);
}else{ // is our case here
List<Fragment> fragments = fragmenting(i);
MyPageAdapter.myFragments = fragments;
mpa.notifyDataSetChanged();
}
ad = mpa;
sViewPager.setAdapter(ad);
sViewPager.setCurrentItem(0);
}
在这个阶段一切正常,如果我去浏览特定数量的片段,它将有效导航,每个片段都有MyFragment
片段的容器。
但是在尝试访问片段的视图时,它仅在第一个两个片段中根据FrameLayout
返回指定的视图(MyFragment
),之后它返回null
,我尝试通过循环mpa
打印出返回的视图:
for(int g =0; g < mpa.getCount(); g++){
System.out.println(mpa.getItem(g));
}
这就是我得到的:
05-12 08:36:10.175: I/System.out(1062): MyFragment{53535b8c #1 id=0x7f06005e}
05-12 08:36:10.175: I/System.out(1062): MyFragment{540e71b4 #0 id=0x7f06005e}
05-12 08:36:10.175: I/System.out(1062): MyFragment{540e7298}
05-12 08:36:10.175: I/System.out(1062): MyFragment{540e737c}
05-12 08:36:10.175: I/System.out(1062): MyFragment{540e7460}
答案 0 :(得分:3)
根据MyFragment in返回指定的View(FrameLayout) 仅前两个片段,之后返回null
适配器的构建效率很高,因此它会破坏无法立即访问的片段的视图(可访问的片段将是当前可见的一侧加一个(为了便于轻扫),除非易于扫描,否则你使用过setOffscreenPageLimit()
)。在您的情况下,如果您在当前页面为for
时调用0
循环,则只会获得有关页面0
和1
的有效片段视图。调用setCurrentItem()
不起作用,因为转换不会立即发生(因此其他片段不会立即构建)。
我不知道你要对片段的观点做些什么,但你需要重新思考你的方法。您不应该像现在一样尝试更新它们,您应该立即更新用户可用的片段(我上面提到的那些片段)。更新其他片段的视图没有意义,因为用户可能根本不使用它们会浪费。
你在代码中做了其他错误,例如:
基于片段列表的适配器必然会失败,因为您将丢失片段的正确引用。适配器不会每次都调用getItem()
方法,在某些情况下,它会自行重新创建片段,使列表引用无效(特别是当您将片段列表声明为静态时)。如果您要使用列表,请确保按顺序保留对片段的引用(例如,您可以获得对适配器的instantiateItem()
方法中使用的实际片段的引用。)
不要让每个类字段像你一样静止。您不应该将视图字段声明为静态,因为它们包含对Context
的引用,并且您可能会泄漏它。片段列表不应该是静态的,因为可能会重新创建使用适配器的片段,在这种情况下,将重新创建适配器本身,但是您的列表将保留旧内容。