我无法更新 ViewPager 中的内容。
FragmentPagerAdapter 类中方法 instantiateItem() 和 getItem() 的正确用法是什么?
我只使用 getItem() 来实例化并返回我的片段:
@Override
public Fragment getItem(int position) {
return new MyFragment(context, paramters);
}
这运作良好。除了我不能改变内容。
所以我发现了这个: ViewPager PagerAdapter not updates the View
“我的方法是对 instanceItem() 方法中的任何实例化视图使用 setTag() 方法”
现在我想实现 instantiateItem() 来做到这一点。但我不知道我必须返回什么(类型是 Object)以及与 getItem(int position) 的关系是什么?
我阅读了 参考资料:
- 公共抽象片段 getItem(int 位置)
返回与指定位置关联的 Fragment。
- public Object instantiateItem(ViewGroup 容器,int 位置)
为给定位置创建页面。适配器负责将视图添加到此处给出的容器中,尽管它只必须确保在它从 finishUpdate(ViewGroup) 返回时完成此操作。参数
容器 将在其中显示页面的包含视图。 position 要实例化的页面位置。
退货
返回一个表示新页面的对象。这不需要是视图,但可以是页面的其他容器。
但我还是不明白。
这是我的代码。我正在使用支持包 v4。
ViewPagerTest
public class ViewPagerTest extends FragmentActivity {
private ViewPager pager;
private MyFragmentAdapter adapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pager1);
pager = (ViewPager)findViewById(R.id.slider);
String[] data = {"page1", "page2", "page3", "page4", "page5", "page6"};
adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
pager.setAdapter(adapter);
((Button)findViewById(R.id.button)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
reload();
}
});
}
private void reload() {
String[] data = {"changed1", "changed2", "changed3", "changed4", "changed5", "changed6"};
//adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
adapter.setData(data);
adapter.notifyDataSetChanged();
pager.invalidate();
//pager.setCurrentItem(0);
}
}
我的片段适配器
class MyFragmentAdapter extends FragmentPagerAdapter {
private int slideCount;
private Context context;
private String[] data;
public MyFragmentAdapter(FragmentManager fm, int slideCount, Context context, String[] data) {
super(fm);
this.slideCount = slideCount;
this.context = context;
this.data = data;
}
@Override
public Fragment getItem(int position) {
return new MyFragment(data[position], context);
}
@Override
public int getCount() {
return slideCount;
}
public void setData(String[] data) {
this.data = data;
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
我的片段
public final class MyFragment extends Fragment {
private String text;
public MyFragment(String text, Context context) {
this.text = text;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.slide, null);
((TextView)view.findViewById(R.id.text)).setText(text);
return view;
}
}
这里也有人有类似问题,没有答案 http://www.mail-archive.com/android-developers@googlegroups.com/msg200477.html
原文由 User 发布,翻译遵循 CC BY-SA 4.0 许可协议
使用 FragmentPagerAdapter 或 FragmentStatePagerAdapter 时,最好单独处理
getItem()
而完全不接触instantiateItem()
。 TheinstantiateItem()
-destroyItem()
-isViewFromObject()
interface on PagerAdapter is a lower-level interface that FragmentPagerAdapter uses to implement the muchgetItem()
interface.在进入这个之前,我应该澄清一下
该答案的早期版本错误地将 FragmentPagerAdapter 用作其示例 - 这将不起作用,因为 FragmentPagerAdapter 在第一次显示后永远不会破坏片段。
我不推荐您链接的帖子中提供的
setTag()
和findViewWithTag()
解决方法。正如您所发现的,使用setTag()
和findViewWithTag()
不适用于片段,所以它不是一个很好的匹配。正确的解决方案是覆盖
getItemPosition()
。当调用getItemPosition()
notifyDataSetChanged()
,ViewPager 会在其适配器中的所有项目上调用 — 以查看它们是否需要移动到不同的位置或删除。默认情况下,
getItemPosition()
返回POSITION_UNCHANGED
,这意味着,“这个对象在它所在的地方很好,不要破坏或删除它。”返回POSITION_NONE
解决了这个问题,而是说,“这个对象不再是我正在显示的项目,删除它。”因此,它具有删除和重新创建适配器中每个项目的效果。这是一个完全合法的修复!此修复使 notifyDataSetChanged 的行为类似于常规适配器,无需视图回收。如果您实施此修复并且性能令人满意,那么您就可以参加比赛了。任务完成。
如果您需要更好的性能,您可以使用更高级的
getItemPosition()
实现。这是一个寻呼机从字符串列表中创建片段的示例:使用此实现,只会显示显示新标题的片段。任何显示仍在列表中的标题的片段都将被移动到它们在列表中的新位置,并且标题不再在列表中的片段将被销毁。
如果片段尚未重新创建,但仍需要更新怎么办?对活动片段的更新最好由片段本身处理。毕竟,这就是拥有片段的优势——它是它自己的控制器。片段可以在
onCreate()
侦听器或观察者添加到另一个对象,然后在onDestroy()
其删除,从而管理更新本身。您不必将所有更新代码放入getItem()
就像您在 ListView 或其他 AdapterView 类型的适配器中所做的那样。最后一件事——仅仅因为 FragmentPagerAdapter 不破坏片段并不意味着 getItemPosition 在 FragmentPagerAdapter 中完全没用。您仍然可以使用此回调在 ViewPager 中重新排序您的片段。但是,它永远不会将它们完全从 FragmentManager 中删除。