ViewPager PagerAdapter不更新视图
我使用兼容库中的ViewPager。 我成功地得到它显示几个我可以翻阅的意见。
但是,我很难弄清楚如何用一组新的视图更新ViewPager。
我尝试了各种各样的东西,比如每次我想使用新的数据列表时, mViewPager.invalidate()
调用mAdapter.notifyDataSetChanged()
, mViewPager.invalidate()
甚至创建一个全新的适配器。
没有任何帮助,文本视图与原始数据保持不变。
更新:我做了一个小测试项目,我几乎可以更新视图。 我将粘贴下面的课程。
然而,没有更新的是第二个视图,“B”仍然存在,按下更新按钮后应该显示“Y”。
public class ViewPagerBugActivity extends Activity {
private ViewPager myViewPager;
private List<String> data;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
data = new ArrayList<String>();
data.add("A");
data.add("B");
data.add("C");
myViewPager = (ViewPager) findViewById(R.id.my_view_pager);
myViewPager.setAdapter(new MyViewPagerAdapter(this, data));
Button updateButton = (Button) findViewById(R.id.update_button);
updateButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
updateViewPager();
}
});
}
private void updateViewPager() {
data.clear();
data.add("X");
data.add("Y");
data.add("Z");
myViewPager.getAdapter().notifyDataSetChanged();
}
private class MyViewPagerAdapter extends PagerAdapter {
private List<String> data;
private Context ctx;
public MyViewPagerAdapter(Context ctx, List<String> data) {
this.ctx = ctx;
this.data = data;
}
@Override
public int getCount() {
return data.size();
}
@Override
public Object instantiateItem(View collection, int position) {
TextView view = new TextView(ctx);
view.setText(data.get(position));
((ViewPager)collection).addView(view);
return view;
}
@Override
public void destroyItem(View collection, int position, Object view) {
((ViewPager) collection).removeView((View) view);
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Parcelable saveState() {
return null;
}
@Override
public void restoreState(Parcelable arg0, ClassLoader arg1) {
}
@Override
public void startUpdate(View arg0) {
}
@Override
public void finishUpdate(View arg0) {
}
}
}
有几种方法可以实现这一点。
第一种选择更容易,但效率更低。
在您的PagerAdapter
重写getItemPosition
,如下所示:
public int getItemPosition(Object object) {
return POSITION_NONE;
}
这样,当您调用notifyDataSetChanged()
,视图分页器将删除所有视图并全部重新载入。 因此获得了重载效果。
第二个选项,由Alvaro Luis Bustamante(以前的alvarolb)建议,在instantiateItem()
化新视图时,在instantiateItem()
Tab setTag()
方法。 然后,您可以使用findViewWithTag()
来查找要更新的视图,而不是使用notifyDataSetChanged()
。
第二种方法非常灵活和高性能。 对原始研究的荣誉alvarolb。
我不认为在PagerAdapter
有任何一种错误。 问题是理解它的工作原理有点复杂。 看看这里解释的解决方案,从我的角度来看,存在误解,因此对实例化视图的使用较差。
最近几天我一直在使用PagerAdapter
和ViewPager
,并且发现了以下内容:
该notifyDataSetChanged()
的方法PagerAdapter
只会通知ViewPager
底层页面发生了变化。 例如,如果您已经动态地创建/删除页面(添加或删除列表中的项目), ViewPager
应该处理这个问题。 在这种情况下,我认为ViewPager
确定是否应该使用getItemPosition()
和getCount()
方法删除或实例化新视图。
我认为ViewPager
在notifyDataSetChanged()
调用之后会接受它的子视图,并用getItemPosition()
检查它们的位置。 如果对于子视图,此方法返回POSITION_NONE
,则ViewPager
理解该视图已被删除,调用destroyItem()
并删除此视图。
这样,如果只想更新页面的内容,重写getItemPosition()
总是返回POSITION_NONE
是完全错误的,因为之前创建的视图将被销毁,并且每次调用notifyDatasetChanged()
时都会创建新视图。 对于一些TextView
,看起来似乎不是那么错误,但是当你有复杂的视图时,比如从数据库填充ListViews,这可能是一个真正的问题,并且会浪费资源。
所以有几种方法可以有效地改变视图的内容,而无需再次移除和实例化视图。 这取决于你想解决的问题。 我的方法是对instantiateItem setTag()
方法中的任何实例化视图使用setTag()
instantiateItem()
方法。 因此,当您想要更改数据或使需要的视图无效时,可以调用ViewPager
上的findViewWithTag()
方法来检索先前实例化的视图,并根据需要修改/使用它,而无需删除/创建新视图每次你想更新一些价值。
想象一下,例如,您有100页100页的TextView
并且您只想定期更新一个值。 使用之前解释的方法,这意味着您要在每次更新中删除并实例化100个TextView
。 它没有任何意义...
将FragmentPagerAdapter
更改为FragmentStatePagerAdapter
。
重写getItemPosition()
方法并返回POSITION_NONE
。
最终,它将侦听查看寻呼机上的notifyDataSetChanged()
。
上一篇: ViewPager PagerAdapter not updating the View
下一篇: How to Create Dynamically numbered Pin Pointers on MapView?