Android:UI控件ViewPager,notifyDataSetChanged
ViewPager的使用: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 public class MainActivity extends Activity { /* *XML添加viewpager方法: *<android.support.v4.view.ViewPager *android:id="@+id/viewPager" *android:layout_width="match_parent" *android:layout_height="match_parent"/> */ int []ImageIds= new int [] {R.drawable.guide_daily_brand,R.drawable.guide_item_detail_1,R.drawable.guide_item_detail_2,R.drawable.guide_multi_shop_detail, R.drawable.guide_pic_mode,R.drawable.guide_timeline_filter}; private ArrayList<View>mViewList= new ArrayList<View>(); @Override protected void onCreate(BundlesavedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); ViewPagerviewPager=(ViewPager)findViewById(R.id.viewPager); viewPager.setAdapter( new PagerAdapter() { @Override public ObjectinstantiateItem(Viewcontainer, int position) { //第一页和最后一页只创建保留两个view来复用,中间则保留三个view LayoutInflaterinflater=getLayoutInflater(); Viewlayout=inflater.inflate(R.layout.pager_item, null ); //将View加入到容器和container里面,不加判断会造成泄漏 if (mViewList.size()<ImageIds.length) { mViewList.add(layout); } ((ViewPager)container).addView(layout, 0 ); layout.setBackgroundResource(ImageIds[position]); return layout; } @Override public void destroyItem(Viewcontainer, int position,Objectobject) { //此处的position与上面的并不相等,会自动销毁不在当前页左右的view ((ViewPager)container).removeView(mViewList.get(position)); } @Override public boolean isViewFromObject(Viewarg0,Objectarg1) { return arg0==arg1; //判断对象与类型 } @Override public int getCount() { return ImageIds.length; } }); } @Override public boolean onCreateOptionsMenu(Menumenu) { getMenuInflater().inflate(R.menu.main,menu); return true ; } } 其他笔记: 1.viewpager切换时容易造成oom问题 1 2 3 4 5 6 mViewPager=(ViewPager)findViewById(R.id.photogallery_viewpager); mAdapter= new PhotoGalleryAdapter(); //限制view的数量,减少view缓存,在setAdapter之前使用 mViewPager.setOffscreenPageLimit( 3 ); mViewPager.setAdapter(mAdapter); mViewPager.setCurrentItem(mPagerSelected); 2.两种removeview方法 1 2 3 4 5 6 @Override public void destroyItem(Viewcontainer, int position,Objectobject) { //((ViewPager)container).removeView((View)object); ((ViewPager)container).removeView(mViewList.get(position)); } 3.关于notifyDataSetChanged()方法无法及时更新的问题解决方法 (1)销毁ViewItem时要使用以下方法: 1 2 3 4 5 6 @Override public void destroyItem(Viewcontainer, int position,Objectobject) { //((ViewPager)container).removeView(mViewList.get(position)); ((ViewPager)container).removeView((View)object); } 参考资料:http://www.myexception.cn/android/417891.html (2)重写notifyDataSetChanged()和getItemPosition(Object object)方法,代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 private int mChildCount= 0 ; @Override public void notifyDataSetChanged() { mChildCount=getCount(); super .notifyDataSetChanged(); } @Override public int getItemPosition(Objectobject) { if (mChildCount> 0 ) { mChildCount--; return POSITION_NONE; } return super .getItemPosition(object); } 参考资料:http://www.cnblogs.com/maoyu417/p/3740209.html 附相关注释: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 进入viewpager,我们终于找到了viewpager中控制数据变更的重点方法dataSetChanged,这个方法如下: void dataSetChanged(){ //Thismethodonlygetscalledifourobserverisattached,somAdapterisnon-null. boolean needPopulate=mItems.size()<mOffscreenPageLimit* 2 + 1 && mItems.size()<mAdapter.getCount(); int newCurrItem=mCurItem; boolean isUpdating= false ; for ( int i= 0 ;i<mItems.size();i++){ final ItemInfoii=mItems.get(i); final int newPos=mAdapter.getItemPosition(ii.object); if (newPos==PagerAdapter.POSITION_UNCHANGED){ continue ; } if (newPos==PagerAdapter.POSITION_NONE){ mItems.remove(i); i--; if (!isUpdating){ mAdapter.startUpdate( this ); isUpdating= true ; } mAdapter.destroyItem( this ,ii.position,ii.object); needPopulate= true ; if (mCurItem==ii.position){ //Keepthecurrentiteminthevalidrange newCurrItem=Math.max( 0 ,Math.min(mCurItem,mAdapter.getCount()- 1 )); needPopulate= true ; } continue ; } if (ii.position!=newPos){ if (ii.position==mCurItem){ //Ourcurrentitemchangedposition.Followit. newCurrItem=newPos; } ii.position=newPos; needPopulate= true ; } } if (isUpdating){ mAdapter.finishUpdate( this ); } Collections.sort(mItems,COMPARATOR); if (needPopulate){ //Resetourknownpagewidths;populatewillrecomputethem. final int childCount=getChildCount(); for ( int i= 0 ;i<childCount;i++){ final Viewchild=getChildAt(i); final LayoutParamslp=(LayoutParams)child.getLayoutParams(); if (!lp.isDecor){ lp.widthFactor= 0 .f; } } setCurrentItemInternal(newCurrItem, false , true ); requestLayout(); } } 重点看这样一行代码: final int newPos=mAdapter.getItemPosition(ii.object); if (newPos==PagerAdapter.POSITION_UNCHANGED){ continue ; } 官方对getItemPosition()的解释是: Calledwhenthehostviewisattemptingtodetermine if anitem’spositionhaschanged.ReturnsPOSITION_UNCHANGED if thepositionofthegivenitemhasnotchangedorPOSITION_NONE if theitemisnolongerpresentintheadapter. The default implementationassumesthatitemswillneverchangepositionandalwaysreturnsPOSITION_UNCHANGED. 意思是如果item的位置如果没有发生变化,则返回POSITION_UNCHANGED。如果返回了POSITION_NONE,表示该位置的item已经不存在了。默认的实现是假设item的位置永远不会发生变化,而返回POSITION_UNCHANGED 解决方案: 所以我们可以尝试着修改适配器的写法,覆盖getItemPosition()方法,当调用notifyDataSetChanged时,让getItemPosition方法人为的返回POSITION_NONE,从而达到强迫viewpager重绘所有item的目的。 本文转自 glblong 51CTO博客,原文链接:http://blog.51cto.com/glblong/1224648,如需转载请自行联系原作者