listview中的item重复问题

Android ListView最佳处理方式,ListView拖动防重复数据显示,单击响应子控件。

1、为了防止拖动ListView时,在列表末尾重复数据显示。需要加入 HashMap<Integer,View> lmap = new HashMap<Integer,View>();其中Integer为列表位置,View为子项视图,加入数据前首先if (lmap.get(position)==null) ,满足条件时,加入lmap.put(position, convertView);如果条件不满足,convertView = lmap.get(position);

2、监听每个子控件时,一定要加入final int currentPosition=position;这样可以牢牢抓住每次点击的响应位置;最好把控件集成到类中。

package logic;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import logic.PlaceAdapter.ViewHolder;

import org.guiji.BigPictureActivity;
import org.guiji.ClassUserListActivity;
import org.guiji.CommentMoodActivity;
import org.guiji.R;
import org.guiji.UserHomeActivity;

import support.ClassUserListImageDownloadTask;
import support.ImageDownloadTask;
import support.SystemConstant;
import android.content.Context;
import android.content.Intent;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class ClassUserListAdapter extends BaseAdapter {
	HashMap<Integer,View> lmap = new HashMap<Integer,View>();
	private LayoutInflater mInflater=null;
	private List<Map<String, String>> mData=null;
	private ClassUserListImageDownloadTask imgtask=null;
	private Context context;
	public List<Map<String, String>> getmData() {
		return mData;
	}

	public void setmData(List<Map<String, String>> mData) {
		this.mData = mData;
	}
	public ClassUserListAdapter(Context context){
		this.mInflater = LayoutInflater.from(context);
		this.context=context;
	}
	@Override
	public int getCount() {
		return mData.size();
	}

	@Override
	public Object getItem(int position) {
		return mData.get(position);
	}

	@Override
	public long getItemId(int position) {
		return position;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		ClassUserListViewHolder holder = null;
        if (lmap.get(position)==null) {
        	imgtask=new ClassUserListImageDownloadTask();

        	convertView = mInflater.inflate(R.layout.classuserlist_item, null);
            holder=new ClassUserListViewHolder(); 

            holder.classuserlist_item_userlogo=(ImageView)convertView.findViewById(R.id.classuserlist_item_userlogo);
            holder.classuserlist_item_username=(TextView)convertView.findViewById(R.id.classuserlist_item_username);
            holder.classuserlist_item_statuscontent=(TextView)convertView.findViewById(R.id.classuserlist_item_statuscontent);
            holder.classuserlist_item_idfans1=(TextView)convertView.findViewById(R.id.classuserlist_item_idfans1);
            holder.classuserlist_item_idfans2=(TextView)convertView.findViewById(R.id.classuserlist_item_idfans2);
            holder.classuserlist_item_idmood=(TextView)convertView.findViewById(R.id.classuserlist_item_idmood);
            holder.classuserlist_item_idhuoyuevalue=(TextView)convertView.findViewById(R.id.classuserlist_item_idhuoyuevalue);
            holder.classuserlist_item_msgpic=(ImageView)convertView.findViewById(R.id.classuserlist_item_msgpic);
            holder.classuserlist_item_msgcontent=(TextView)convertView.findViewById(R.id.classuserlist_item_msgcontent);
            holder.classuserlist_item_idtimeplace=(TextView)convertView.findViewById(R.id.classuserlist_item_idtimeplace);
            holder.classuserlist_item_classbutton=(ImageView)convertView.findViewById(R.id.classuserlist_item_classbutton);

            lmap.put(position, convertView);
            convertView.setTag(holder);

            holder.classuserlist_item_username.setText((String)mData.get(position).get("username"));
            if(mData.get(position).get("idstatuscontent")!=null){
            	holder.classuserlist_item_statuscontent.setText((String)mData.get(position).get("idstatuscontent"));
            	holder.classuserlist_item_statuscontent.setVisibility(0);
            }
            if(mData.get(position).get("idfans1")!=null){
            	holder.classuserlist_item_idfans1.setText((String)mData.get(position).get("idfans1"));
            	holder.classuserlist_item_idfans1.setVisibility(0);
            }
            if(mData.get(position).get("idfans2")!=null){
            	holder.classuserlist_item_idfans2.setText((String)mData.get(position).get("idfans2"));
            	holder.classuserlist_item_idfans2.setVisibility(0);
            }

            holder.classuserlist_item_idmood.setText((String)mData.get(position).get("idmood"));
            if(mData.get(position).get("idhuoyuevalue").length()>=4)
            	holder.classuserlist_item_idhuoyuevalue.setText("活跃值"+"("+mData.get(position).get("idhuoyuevalue").substring(0, 4)+")");
            else
            	holder.classuserlist_item_idhuoyuevalue.setText("活跃值"+"("+mData.get(position).get("idhuoyuevalue")+"0"+")");

            if(mData.get(position).get("idmsgcontent")!=null){
            	holder.classuserlist_item_msgcontent.setText((String)mData.get(position).get("idmsgcontent"));
            	holder.classuserlist_item_msgcontent.setVisibility(0);
            }
            if(mData.get(position).get("idtime")!=null){
            	holder.classuserlist_item_idtimeplace.setText((String)mData.get(position).get("idtime")+"  "+(String)mData.get(position).get("idplace"));
            	holder.classuserlist_item_idtimeplace.setVisibility(0);
            }

            String temp=SystemConstant.baseURLNone+mData.get(position).get("userlogo")+","+
    		SystemConstant.baseURLNone+mData.get(position).get("idmsgpic");
            imgtask.execute(temp,holder);

        }else {
        	convertView = lmap.get(position);
            holder = (ClassUserListViewHolder)convertView.getTag();
        }

        final int currentPosition=position;
        holder.classuserlist_item_userlogo.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				MainService.guiji.setCurrentURL(SystemConstant.baseURL+mData.get(currentPosition).get("userLink"));
				Intent it=new Intent(context,UserHomeActivity.class);
				context.startActivity(it);
			}
		});

        holder.classuserlist_item_username.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				MainService.guiji.setCurrentURL(SystemConstant.baseURL+mData.get(currentPosition).get("userLink"));
				Intent it=new Intent(context,UserHomeActivity.class);
				context.startActivity(it);
			}
		});
        holder.classuserlist_item_msgpic.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				MainService.guiji.setCurrentURL(SystemConstant.baseURLNone+mData.get(currentPosition).get("idmsgpic"));
				Intent it=new Intent(context,BigPictureActivity.class);
				context.startActivity(it);
			}
		});
        holder.classuserlist_item_idfans1.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				MainService.guiji.deleteReply(SystemConstant.baseURL+mData.get(currentPosition).get("idfans1link"));
				((ClassUserListActivity) context).createTask();
			}
		});
        holder.classuserlist_item_idfans2.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				MainService.guiji.deleteReply(SystemConstant.baseURL+mData.get(currentPosition).get("idfans2link"));
				((ClassUserListActivity) context).createTask();
			}
		});

        holder.classuserlist_item_classbutton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				String temp=SystemConstant.baseURL+mData.get(currentPosition).get("idcommentlink");
//				MainService.guiji.setCurrentURL(temp);
				MainService.guiji.setPageType(4);
				MainService.guiji.setBackURL(temp);
				Intent it=new Intent(context,CommentMoodActivity.class);
				context.startActivity(it);
			}
		});

		return convertView;
	}
	public class ClassUserListViewHolder{
		public ImageView classuserlist_item_userlogo;
		public TextView classuserlist_item_username;
		public TextView classuserlist_item_statuscontent;
		public TextView classuserlist_item_idfans1;
		public TextView classuserlist_item_idfans2;
		public TextView classuserlist_item_idmood;
		public TextView classuserlist_item_idhuoyuevalue;
		public ImageView classuserlist_item_msgpic;
		public TextView classuserlist_item_msgcontent;
		public TextView classuserlist_item_idtimeplace;
		public ImageView classuserlist_item_classbutton;
	}

}

ListView在开发中是一个经常用的控件,有时候为了扩展更多功能也会用到ExpandableListView,然而数据的正确显示是开发者在实际开发中需要注意的,我在实现ListView的时候,最常遇到的是数据重复显示还有快速滑动的时候数据显示不完整的现象,然而如果在数据量大的时候还涉及到性能和convertView重用的问题。上面的这种处理方式,似乎已经比较好了,我已经验证过,之前滑动列表出现数据重复和显示不完整的现象全都没了。

Android ListView图片显示重复错乱闪烁问题在滑动过程中的解决办法

主要分析Android ListView滚动过程中图片显示重复、错乱、闪烁的原因及解决方法,顺带提及ListView的缓存机制。 1、原因分析 ListView item缓存机制:为了使得性能更优,ListView会缓存行item(某行对应的View)。ListView通过adapter的getView函数获得每行的item。滑动过程中,

a. 如果某行item已经滑出屏幕,若该item不在缓存内,则put进缓存,否则更新缓存; b. 获取滑入屏幕的行item之前会先判断缓存中是否有可用的item,如果有,做为convertView参数传递给adapter的getView。 更具体可见源代码ListView.obtainView

这样,如下的getView写法就可以充分利用缓存大大提升ListView的性能。即便上万个行item,最多inflate的次数为n,n为一屏最多显示ListView 行item的个数。

ListView Adapter getView写法

<span style="line-height: 20px; ">@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder;
    if (convertView == null) {
        convertView = inflater.inflate(R.layout.list_item, null);
        holder = new ViewHolder();
        ……
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder)convertView.getTag();
    }
}

/**
 * ViewHolder
 *
 * @author [email protected] 2013-08-01
 */
private static class ViewHolder {

    ImageView appIcon;
    TextView  appName;
    TextView  appInfo;
}</span>

这样提升了性能,但同时也会造成另外一些问题:
a. 行item图片显示重复  这个显示重复是指当前行item显示了之前某行item的图片。  比如ListView滑动到第2行会异步加载某个图片,但是加载很慢,加载过程中listView已经滑动到了第14行,且滑动过程中该图片加载结束,第2行已不在屏幕内,根据上面介绍的缓存原理,第2行的view可能被第14行复用,这样我们看到的就是第14行显示了本该属于第2行的图片,造成显示重复。
b. 行item图片显示错乱  这个显示错乱是指某行item显示了不属于该行item的图片。  比如ListView滑动到第2行会异步加载某个图片,但是加载很慢,加载过程中listView已经滑动到了第14行,第2行已不在屏幕内,根据上面介绍的缓存原理,第2行的view可能被第14行复用,第14行显示了第2行的View,这时之前的图片加载结束,就会显示在第14行,造成错乱。
c. 行item图片显示闪烁  上面b的情况,第14行图片又很快加载结束,所以我们看到第14行先显示了第2行的图片,立马又显示了自己的图片进行覆盖造成闪烁错乱。
2、解决方法  通过上面的分析我们知道了出现错乱的原因是异步加载及对象被复用造成的,如果每次getView能给对象一个标识,在异步加载完成时比较标识与当前行item的标识是否一致,一致则显示,否则不做处理即可。  下面以使用ImageCache为ListView提供图片获取缓存为例,ListView中强烈推荐使用ImageCache。  首先在listview adapter的getView中添加

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder;
    if (convertView == null) {
        convertView = inflater.inflate(R.layout.list_item, null);
        holder = new ViewHolder();
        ……
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder)convertView.getTag();
    }

    ……
    // add tag for image, to compare it when image loaded finish
    imageView.setTag(imageUrl);
    // if not in cache, restore default
    if (!Cache.ICON_CACHE.get(imageUrl, imageView)) {
        imageView.setImageDrawable(null);
    }
}

其中setTag表示设置标识,方便下面进行标志比对

if (!Cache.ICON_CACHE.get(imageUrl, imageView))

1

if (!Cache.ICON_CACHE.get(imageUrl, imageView))

Cache.ICON_CACHE为ImageCache的实例,表示如果不在缓存内则设置drawable为null(当然你可以可以设置为你自己的默认资源),防止显示了之前某个行item的图片,解决了a.  行item图片显示重复问题。

在ImageCache的OnImageCallbackListener的onGetSuccess函数中添加

Java

public void onGetSuccess(String imageUrl, Drawable imageDrawable, View view, boolean isInCache) {
// can be another view child, like textView and so on
if (view != null && imageDrawable != null) {
ImageView imageView = (ImageView)view;
// add tag judge, avoid listView cache and so on
String imageUrlTag = (String)imageView.getTag();
if (ObjectUtils.isEquals(imageUrlTag, imageUrl)) {
imageView.setImageDrawable(imageDrawable);
}
}
};

1

2

3

4

5

6

7

8

9

10

11

public void onGetSuccess(String imageUrl, Drawable imageDrawable, View view, boolean isInCache) {

// can be another view child, like textView and so on

if (view != null && imageDrawable != null) {

ImageView imageView = (ImageView)view;

// add tag judge, avoid listView cache and so on

String imageUrlTag = (String)imageView.getTag();

if (ObjectUtils.isEquals(imageUrlTag, imageUrl)) {

imageView.setImageDrawable(imageDrawable);

}

}

};

在上面用String imageUrlTag = (String)imageView.getTag();取得之前设置的tag,然后和当前的url进行比较,如果相等则显示,解决了b. 行item图片显示错乱,c. 行item图片显示错乱的两个问题。其中ObjectUtils可见[email protected].

其他异步加载过程解决原理类似。

时间: 2024-08-29 05:08:00

listview中的item重复问题的相关文章

Android动态加载ListView中的Item

我这周上网看到动态增加listview的每一项item的布局,今天抽空自己写了一个,方便自己日后使用,这个效果还是很不错的,用到了Adapter的notifyDataSetChanged()方法,当点击每一个Item的时候,就通知adapter更新getView,系统得到通知就相应的加载一遍布局,就达到了动态加载item布局的效果.希望给大家带来点启迪,有问题或想要代码的可以留言,欢迎大家留言谈论listview的一些知识,以求共同进步,转载请标明出处: http://blog.csdn.net

删除ListView中所有Item项

今天做项目遇到一个一键删除ListView中所有列表项的需求,这里自己记录一下. 刚开始的想法是将设置一个空的Adapter,让后将空的Adapter赋给ListView,但后来想想这样太麻烦了,就去寻找了一下官方时候给了这样的方法. 别说,还真的有类似的方法! ViewGroup类下面有一个removeAllViews()方法,看名字就很像,试了一下竟然不行! 报了这样的错误: removeAllViews() is not supported in AdapterView 竟然说这个不是给A

android ListView中的Item有Button时候点击异常处理

1.当ListView中有Button的时候往往会遇到很多问题,比较常见的一个问题是: 假设:在ListView中有N个Item当点击其中某个Item中的Button的时候,需要改变当前Button的状态,在你点击以后确实最后一个Item的Button的状态改变了,不管点击哪一个Button都是最后一个 Item的中的Button的状态被改变了,这里涉及到ListView重绘的问题. 要解决上面的问题的方法是将点击的监听事件提出来进行封装,在用就可以解决上述问题了. 给个示例代码: 在ListV

Gridview, ListView中的item含有checkbox,setOnItemClickListener方法失效的问题

1) 设置CheckBoxandroid:clickable="false"  通过外部View的点击改变其状态. <CheckBox android:id="@+id/select_tag" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignRight="@+id/album

ListView中的item中的Onclick事件的优化

ListView的Adapter的优化布局载入器的载入次数最典型的使用方法是使用convertView进行优化,让convertView当做布局载入器的载体,也就是.重用 convertView 用以避免反复创建 View.反复创建 View 代价较大,并且假设重用 view 不改变宽高,重用View能够降低又一次分配缓存造成的内存频繁分配/回收; convertView = LayoutInflater.from(context).inflate(R.layout.子布局, null) 避免在

ListView中每个item条目在被单击选中时能够高亮显示

在布局文件中设定: android:listSelector="@android:color/holo_red_light" 在代码中实现 listView.setSelector(android.R.color.holo_orange_light);

ListView中的Item点击事件和子控件的冲突或者item点击没有反应的解决办法

fragment中添加了button和checkbox这些控件,此时这些子控件会将焦点获取到,所以常常当点击item时变化的是子控件,item本身的点击没有响应. 这时候就可以使用descendantFocusability来解决啦,API描述如下: android:descendantFocusability 该属性是当一个为view获取焦点时,定义viewGroup和其子控件两者之间的关系. 属性的值有三种: beforeDescendants:viewgroup会优先其子类控件而获取到焦点

android捕获ListView中每个item点击事件

package com.wps.android; import java.util.ArrayList; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListe

如何让ListView中的item里面的selector生效?

============问题描述============ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"     android:layout_width="match_parent"     android:layout_height