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(Bundle savedInstanceState)
     {
         super .onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
                                
         ViewPager viewPager = (ViewPager) findViewById(R.id.viewPager);
         viewPager.setAdapter( new  PagerAdapter()
         {
             @Override
             public  Object instantiateItem(View container,  int  position)
             {
                 //第一页和最后一页只创建保留两个view来复用,中间则保留三个view
                 LayoutInflater inflater = getLayoutInflater();
                 View layout = 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(View container,  int  position, Object object)
             {
                 //此处的position与上面的并不相等,会自动销毁不在当前页左右的view
                 ((ViewPager) container).removeView(mViewList.get(position));
             }
                                    
             @Override
             public  boolean  isViewFromObject(View arg0, Object arg1)
             {
                 return  arg0 == arg1; //判断对象与类型
             }
                                    
             @Override
             public  int  getCount()
             {
                 return  ImageIds.length;
             }
         });
                                
     }
                            
     @Override
     public  boolean  onCreateOptionsMenu(Menu menu)
     {
         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(View container,  int  position, Object object)
         {
//             ((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(View container,  int  position, Object object)
         {
//            ((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(Object object)
         {
             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 () {
         // This method only gets called if our observer is attached, so mAdapter is non-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  ItemInfo ii = 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 ) {
                     // Keep the current item in the valid range
                     newCurrItem = Math. max( 0 , Math.min(mCurItem, mAdapter.getCount() -  1 ));
                     needPopulate =  true ;
                 }
                 continue ;
             }
  
             if  (ii.position != newPos) {
                 if  (ii.position == mCurItem ) {
                     // Our current item changed position. Follow it.
                     newCurrItem = newPos;
                 }
  
                 ii. position = newPos;
                 needPopulate =  true ;
             }
         }
  
         if  (isUpdating) {
             mAdapter.finishUpdate(  this );
         }
  
         Collections. sort(mItems, COMPARATOR);
  
         if  (needPopulate) {
             // Reset our known page widths; populate will recompute them.
             final  int  childCount = getChildCount();
             for  ( int  i =  0 ; i < childCount; i++) {
                 final  View child = getChildAt(i);
                 final  LayoutParams lp = (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()的解释是:
   Called when the host view is attempting to determine  if  an item’s position has changed. Returns POSITION_UNCHANGED  if  the position of the given item has not changed orPOSITION_NONE  if  the item is no longer present in the adapter.
The  default  implementation assumes that items will never change position and always returns POSITION_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,如需转载请自行联系原作者
目录
相关文章
|
1月前
|
搜索推荐 Android开发 开发者
探索安卓开发中的自定义视图:打造个性化UI组件
【10月更文挑战第39天】在安卓开发的世界中,自定义视图是实现独特界面设计的关键。本文将引导你理解自定义视图的概念、创建流程,以及如何通过它们增强应用的用户体验。我们将从基础出发,逐步深入,最终让你能够自信地设计和实现专属的UI组件。
|
3天前
|
移动开发 前端开发 Java
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
JavaFX是Java的下一代图形用户界面工具包。JavaFX是一组图形和媒体API,我们可以用它们来创建和部署富客户端应用程序。 JavaFX允许开发人员快速构建丰富的跨平台应用程序,允许开发人员在单个编程接口中组合图形,动画和UI控件。本文详细介绍了JavaFx的常见用法,相信读完本教程你一定有所收获!
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
|
22天前
|
XML 搜索推荐 前端开发
安卓开发中的自定义视图:打造个性化UI组件
在安卓应用开发中,自定义视图是一种强大的工具,它允许开发者创造独一无二的用户界面元素,从而提升应用的外观和用户体验。本文将通过一个简单的自定义视图示例,引导你了解如何在安卓项目中实现自定义组件,并探讨其背后的技术原理。我们将从基础的View类讲起,逐步深入到绘图、事件处理以及性能优化等方面。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的见解和技巧。
|
1月前
|
XML 前端开发 Android开发
Android:UI:Drawable:View/ImageView与Drawable
通过本文的介绍,我们详细探讨了Android中Drawable、View和ImageView的使用方法及其相互关系。Drawable作为图像和图形的抽象表示,提供了丰富的子类和自定义能力,使得开发者能够灵活地实现各种UI效果。View和ImageView则通过使用Drawable实现了各种图像和图形的显示需求。希望本文能为您在Android开发中使用Drawable提供有价值的参考和指导。
40 2
|
1月前
|
人工智能 API Apache
推荐3款开源、美观且免费的WinForm UI控件库
推荐3款开源、美观且免费的WinForm UI控件库
216 6
|
1月前
|
API C# 开发者
基于Material Design风格开源、免费的WinForms UI控件库
基于Material Design风格开源、免费的WinForms UI控件库!
|
2月前
|
Linux C# Android开发
分享3款开源、免费的Avalonia UI控件库
分享3款开源、免费的Avalonia UI控件库
265 0
|
3月前
|
XML Android开发 UED
💥Android UI设计新风尚!掌握Material Design精髓,让你的界面颜值爆表!🎨
随着移动应用市场的蓬勃发展,用户对界面设计的要求日益提高。为此,掌握由Google推出的Material Design设计语言成为提升应用颜值和用户体验的关键。本文将带你深入了解Material Design的核心原则,如真实感、统一性和创新性,并通过丰富的组件库及示例代码,助你轻松打造美观且一致的应用界面。无论是色彩搭配还是动画效果,Material Design都能为你的Android应用增添无限魅力。
86 1
|
2月前
|
XML 存储 Java
浅谈Android的TextView控件
浅谈Android的TextView控件
47 0
|
3月前
|
XML 编解码 Android开发
安卓开发中的自定义视图控件
【9月更文挑战第14天】在安卓开发中,自定义视图控件是一种高级技巧,它可以让开发者根据项目需求创建出独特的用户界面元素。本文将通过一个简单示例,引导你了解如何在安卓项目中实现自定义视图控件,包括创建自定义控件类、处理绘制逻辑以及响应用户交互。无论你是初学者还是有经验的开发者,这篇文章都会为你提供有价值的见解和技巧。
58 3