在listView适配器的内存优化给点击事件带来的麻烦
来源:互联网 发布:淘宝闺蜜投诉平台 编辑:程序博客网 时间:2024/05/29 18:16
最近做了一个listview,想在点击Item的时候让这个Item的图标改变,监听器在适配器里面做,结果跑起来发现,点击之后,改变图标的竟然不是所点击的Item,而是屏幕中最后一个Item(注意!不是最后一个Item,而是屏幕中已经显示的Item的最后一个)
先贴一段适配器代码
public class DetailAdapter extends BaseAdapter { private List<FoodDetail> foodDetail; private LayoutInflater layoutInflater;//加载布局的准备工作 private Context context; private int local; private int [] image; ViewHolder holder; public DetailAdapter(List<FoodDetail> foodDetail,Context context,int[] image) { this.foodDetail = foodDetail; this.context=context; layoutInflater = LayoutInflater.from(context); this.image = image; } @Override public int getCount() { // TODO Auto-generated method stub return foodDetail.size(); } @Override public Object getItem(int position) { // TODO Auto-generated method stub return foodDetail.get(position); } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub local = position; if (convertView == null) { holder = new ViewHolder(); convertView = layoutInflater.inflate(R.layout.listview_detail, null); holder.relativeLayout = (RelativeLayout) convertView.findViewById(R.id.one); holder.imageView = (ImageView) convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } holder.imageView.setBackgroundResource(image[position]);holder.imageView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //注意设置imageview背景这段话 holder.imageView.setBackground(background); } }); return convertView; } public static class ViewHolder { public ImageView imageView; }}
如上面代码,在onClick()方法里修改Imageview的背景,实际上所修改的不是你当前所点击的Item,而是屏幕中所显示的最后一条Item的Imageview!
注意!!!!!不是最后一个Item,而是屏幕中所显示的最后一个Item。这一切都是listview在内存优化方面做的太好的“错”!
下面顺便说下lisview的内存机制
先看一张图片:
注意里面test数值的变化(不要看a),test变量是我在getView()方法里定义的一个final的int常量,final int test = (int) ( 50 * Math.random() + 50);
值为50-100的随机数,点击listview的任意一个Item,就会打印log日志!通过我的多次实验,发现如果不滑动listview,只是一直点击某一个Item的时候,test的数值是不会改变的!然而,当你滑动listview之后,再次点击这个Item,就会发现test的值已经改变!
这也验证了listview的加载过程不是一下子全部加载,而是至加载一部分,滑动之前的test在滑动的时候,会被内存多次收回和重新建立,当再次回到你滑动之前的Item的时候,这个常量已经不再是当年的那个常量了;
上个图:
下面解释一下:
1、如果你有几千几万甚至更多的选项(item)时,其中只有可见的项目(满屏显示的Item数目)存在内存(说的优化就是说在内存中的优化!)中,其他的在Recycler中
2、ListView先请求一个type1视图(getView)然后请求其他可见的项目。convertView在getView中是空(null)的,第一次都是为空的,只要显示过了convertView都不为空,会保存在Recycler中
3、当item1滚出屏幕,并且一个新的项目从屏幕低端上来时,ListView再请求一个type1视图。convertView此时不是空值了,它的值是item1。你只需设定新的数据然后返回convertView,不必重新创建一个视图,省去了inflate和findViewById的时间,性能就得到了优化。
接着说上面的问题:当你older.imageView.setBackground(background);的时候,实际上,这个控件已经不是你点击的那个Item的了。而是指向屏幕中显示的最后一个Item。所以才造成了无论我点击屏幕中的任何Item,都只是最后一个Item在改变
。
解决的方法就是使用监听事件里的参数去获取你想要改变的布局,就是那个View v参数,
public void onClick(View v) { holder.imageView.setBackground(background); }
使用这个v.getparent()一层层获取到你想要的东西,最后要记住强制转换,因为你获取到的是view控件,也许没有你想要的方法。
或者,简单粗暴:
holder.ImageButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //通过v获取当前你的所点击的Item ImageButton imageButton = (ImageButton) v; imageButton.setBackgroundResource(R.drawable.started); } });
这样,天下太平,你点击哪个Item,哪个Item的图标就改变!!
最后,希望大家多多指教,欢迎补充更好的方法!
- 在listView适配器的内存优化给点击事件带来的麻烦
- gcc编译器优化给我们带来的麻烦???
- session给我带来的麻烦
- 世界杯给IT带来的麻烦
- android listview适配器里区分不同按钮的点击事件
- android listview适配器里区分不同按钮的点击事件
- android listview适配器里区分不同按钮的点击事件
- android listview适配器里区分不同按钮的点击事件
- DirectX9带来的麻烦
- 内码带来的麻烦
- StrPCopy带来的麻烦
- switch带来的麻烦
- DontDestroyOnLoad带来的麻烦
- 《《内存和性能优化》》给我带来的!
- MAXTHON浏览器给CSDN博客带来的小麻烦!
- DOCTYPE差异给页面开发带来的小麻烦
- listview的点击事件
- ListView的点击事件
- windows下用Eclipse编译运行android原生浏览器
- Android中枚举enum的使用
- 【SCOI2013】【BZOJ3323】多项式的运算
- HashMap
- [树状数组+上升子序列] HDU 3030 Increasing Speed Limits
- 在listView适配器的内存优化给点击事件带来的麻烦
- 普通内部类详解
- c++ builder TADOQuery控件的type mismatch for field‘note',expecting: String actual: Memo.
- RMQ算法
- 258Add Digits
- ROS 进阶学习笔记(12) - Communication with ROS through USART Serial Port
- Android日志系统驱动程序Logger源代码分析
- RMQ (Range Minimum/Maximum Query)算法
- iOS视图控制对象生命周期-init、viewDidLoad、viewWillAppear、viewDidAppear、viewWillDisappear、viewDidDisappear的区别及用途