我在一个详细视图中使用ViewPager和FragmentPagerAdapter。这意味着我有一个项目列表,一个屏幕显示单个项目的细节。但用户可以左右滑动来浏览所有项目。这遵循了谷歌滑动视图的指导方针。
但是我想知道一件事。在ListView中,每一行的视图都会被重用。一旦一行从屏幕上滚动出来,它就会被重用为绑定到ListView的适配器的getView方法的转换器视图参数。但是这种重用行为似乎并没有为滑动视图实现。这个例子说明了这一点:
class DemoAdapter extends ArrayAdapter<DemoItem> {
public DemoAdapter(Context context, List<DemoItem> objects) {
super(context, 0, objects);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
// create a new view, otherwise re-use the existing convertView
LayoutInflater i = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = i.inflate(R.layout.list_item_demo, parent, false);
}
// get current item
DemoItem item = getItem(position);
if (item == null)
return convertView;
// update view with the item
TextView textTitle = (TextView)convertView.findViewById(R.id.demo_title);
if (textTitle != null)
textTitle.setText(item.getTitle());
return convertView;
}
}
但问题是:FragmentPageRadepter和FragmentStatePagerAdapter都在其getItem方法中创建片段(每个屏幕都是片段)。但它们不会将旧片段作为输入参数。唯一的区别是,FragmentStatePagerAdapter会销毁未使用的片段。
public class DemoItemsPagerAdapter extends FragmentPagerAdapter {
private final Context context;
public DemoItemsPagerAdapter(FragmentManager fm, Context context) {
super(fm);
this.context = context;
// ToDo: get cursor or array of available items that can be swiped through
}
@Override
public Fragment getItem(int i) {
Fragment fragment = new DemoItemFragment();
// ToDo: initialize fragment by correct item
// ToDo: avoid creating too many fragments - try reusing them (but how?)
return fragment;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
// the container is not the fragment, but the ViewPager itself
return super.instantiateItem(container, position);
}
@Override
public CharSequence getPageTitle(int position) {
// ToDo: return name for current entry
return null;
}
@Override
public int getCount() {
// ToDo: get count from cursor/array of available items
return 2;
}
}
那么,我如何重用这些片段呢?实际上,应该只调用两次getItems,因为一次只有一个片段是可见的,而当用户滑动时,转换开始后会有第二个片段。
更新:由于混淆,我创建了这幅图。它显示了适配器的行为。默认的一个将所有片段保存在内存中,除非设备运行内存溢出。一个应用程序在后台或被杀死,然后恢复每个片段将从其SavedInstanceState中恢复。第二个实现只在内存中保留一些片段,但如果您向左/向右滑动,被销毁的片段将从头开始重新完全创建。我正在寻找第三个实现。您只有三个片段,然后在向左或向右滑动时重复使用。所以片段A可以是位置1、2、3、4、5、6和7。
首先回答你的问题。
那么,我该如何重用碎片呢?
您可以在稀疏数组中维护一个片段数组(当您需要将对象映射到整数时,它比HashMap的内存效率更高)。
private SparseArray<BaseFragment> fragments;
所以你的代码在getItem(int i)
中可以是这样的。
@Override
public Fragment getItem(int position) {
// Create a new fragment only when the fragment is not present in the fragments sparse
// array
BaseFragment fragment = fragments.get(position);
if (fragment == null) {
switch (position) {
case 0: {
fragment = new Fragment1();
fragments.put(0, fragment);
break;
}
case 1: {
fragment = new Fragment2();
fragments.put(1, fragment);
break;
}
.
.
.
default:
fragment = null;
}
}
return fragment;
}
在这里,我使用BaseFragment,它几乎被我想使用的所有片段所扩展。
AFAIK,getItem()
是基于offScreenPageLimit调用的。默认值为 1。因此,基于此数字,将保留在内存中的片段将是
1 + 2*offScreenPageLimit // Current Page + 2 * left/right items
或者
1 + offScreenPageLimit // if its the first or last page.
更新 1
您不必担心从内存中删除片段的问题。FragmentStatePagerAdapter会自动为您处理这些问题,正如他们在文档中提到的那样。
当有大量页面时,此版本的寻呼机更有用,工作更像列表视图。当页面对用户不可见时,它们的整个片段可能会被销毁,只保留该片段的保存状态。与FragmentPagerAdapter相比,这允许寻呼机保留与每个访问页面相关的更少内存,但代价是在页面之间切换时可能会增加开销。
当您要滑动的页面较少时,通常在使用选项卡或片段为静态时,使用FragmentPagerAdapter。医生说,
这种版本的分页器最适合在有少量静态片段需要分页时使用,比如一组选项卡。用户访问的每个页面的片段将保存在内存中,尽管它的视图层次结构在不可见时可能会被破坏。这可能导致使用大量内存,因为片段实例可以保存任意数量的状态。对于较大的页面集,考虑FragmentStatePagerAdapter。
更新2
您上面对案例2的定义是错误的。
第二个实现只在内存中保留一些片段,但是如果您向左/向右滑动,则会从头开始完全再次创建被破坏的片段。
它不会从头创建,它将保存以前创建的片段的状态,并在创建新片段时使用相同的状态。您可以在这里查看源代码,以更好地了解其工作原理。
至于您的第三个实现,我建议覆盖适配器的默认行为,然后根据当前位置手动从适配器中删除/添加视图。
本文向大家介绍Android ViewPager基本用法和片段,包括了Android ViewPager基本用法和片段的使用技巧和注意事项,需要的朋友参考一下 示例 AViewPager允许在活动中显示多个片段,可通过向左或向右翻转来导航。甲ViewPager需要被馈送通过使用任一视图或片段的PagerAdapter。 但是,在使用片段分别为FragmentPagerAdapter和的情况下,有两
MainActivity(扩展了fragmentActivity)有listview,它调用listviewadapter,其中有一个带有ViewpagerAdapter的ViewPager。现在,如果我需要在ViewPager中生成5个片段,如何将getFragmentManager()传递给适配器。 MainActivity[fragmentActivity]---->Listview----
解释 最近,我一直在与碎片和viewpager进行大量的斗争。 我发现ViewPager可以保存你想要的任意多的片段。当它首次实例化时,根据类型(vsFragmentPagerAdapter和FragmentStatePagerAdapter之间的差异),它将创建所有片段或只创建“需要的”片段。 您可以看到,返回null,尽管您是在被触发后调用此方法的。 如果您决定将保留的上下文强制转换为活动,以
但问题是espresso看起来是所有的页面,而不仅仅是当前页面,我得到以下错误: Android.support.test.espresso.ambiguousViewMatcherException:“with id:eu.airpatrol.android:id/container_weather”匹配层次结构中的多个视图...
有没有什么好的方法来引用用创建的片段?或者我应该如何从我的活动(准确地说是从选项菜单)中刷新查看页中的片段?