首页 > 代码库 > ListView数据错位问题
ListView数据错位问题
今天同事做一个发送语音的功能,发现点击语音播放的时候,实际播放语音的喇叭不是点击的那个,而是跳到别的地方了,他的代码如下
public View getView(int position, View convertView, ViewGroup parent) { ChatMsgEntity entity = coll.get(position); boolean isComMsg = entity.getMsgType(); LayoutInflater mInflater = (LayoutInflater)context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); ViewHolder viewHolder=null; if (convertView == null) { if (isComMsg) { convertView = mInflater.inflate( R.layout.chatting_item_msg_text_left, null); } else { convertView = mInflater.inflate( R.layout.chatting_item_msg_text_right, null); } viewHolder = new ViewHolder(); viewHolder.tvSendTime = (TextView) convertView .findViewById(R.id.tv_sendtime); viewHolder.tvUserName = (TextView) convertView .findViewById(R.id.tv_username); viewHolder.tvContent = (TextView) convertView .findViewById(R.id.tv_chatcontent); viewHolder.icon = (ImageView) convertView .findViewById(R.id.iv_userhead); viewHolder.chatPic = (ImageView) convertView .findViewById(R.id.chat_img); viewHolder.isComMsg = isComMsg; convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } final String mass = entity.getMessage(); OnClickListener listener = new View.OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub if (mass.contains("/storage/")&&mass.endsWith(".jpg")) { }else if (mass.contains("/storage/")&&mass.endsWith(".amr")) { if (judgeAnmi) { ad.start(); judgeAnmi = !judgeAnmi; }else { ad.stop(); judgeAnmi = !judgeAnmi; } } } }; viewHolder.tvSendTime.setText(entity.getDate()); viewHolder.tvUserName.setText(entity.getName()); if (mass.contains("/storage/")&&mass.endsWith(".jpg")) { Bitmap bm = convertToBitmap(entity.getMessage(),200,200); BitmapDrawable bd = new BitmapDrawable(bm); viewHolder.chatPic.setBackgroundDrawable(bd); viewHolder.tvContent.setText(""); }else if(mass.contains("/storage/")&&mass.endsWith(".amr")){ viewHolder.chatPic.setBackgroundResource(R.anim.voice_muti); ad = (AnimationDrawable) viewHolder.chatPic.getBackground(); viewHolder.tvContent.setText(mass.substring(0, mass.indexOf("/"))+"″"); }else { viewHolder.tvContent.setText(mass); viewHolder.chatPic.setBackgroundDrawable(null); } viewHolder.chatPic.setOnClickListener(listener); return convertView; }先看看google官方demo的写法
public View getView(int position, View convertView, ViewGroup parent) { // A ViewHolder keeps references to children views to avoid unneccessary calls // to findViewById() on each row. ViewHolder holder; // When convertView is not null, we can reuse it directly, there is no need // to reinflate it. We only inflate a new View when the convertView supplied // by ListView is null. if (convertView == null) { convertView = mInflater.inflate(R.layout.list_item_icon_text, null); // Creates a ViewHolder and store references to the two children views // we want to bind data to. holder = new ViewHolder(); holder.text = (TextView) convertView.findViewById(R.id.text); holder.icon = (ImageView) convertView.findViewById(R.id.icon); convertView.setTag(holder); } else { // Get the ViewHolder back to get fast access to the TextView // and the ImageView. holder = (ViewHolder) convertView.getTag(); } // Bind the data efficiently with the holder. holder.text.setText(DATA[position]); holder.icon.setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2); return convertView; } static class ViewHolder { TextView text; ImageView icon; } }
后来他将viewHolder的定义改为final ViewHolder就解决了问题。
大概想了一下,因为android对ListView做了缓存优化,实际上内存里只保留了一屏幕的View,也就是参数里面的convertView,而之前viewHolder是在convertView为空的时候new出来的,并被convertView setTag进去了,所以,后面取出来的ViewHold对象都是缓存的。但是对于每个holder里面的chatPic都要设定一个点击事件监听器。所以,其实只是对缓存的那些holder对象重复设置监听器。但是为什么将holder对象用final修饰就没问题了,由于final修饰的引用不会改变他所指向的对象。然后为什么这样就可以了我也想不清了,求看到的大神详解。
ListView数据错位问题
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。