大体总结:
1.listView 宽高不能是wrap_content否则会调用 measureheightofchilden会调用两次 (浪费)
2.covertview(xml由infaler填充生成)什么时候为null 什么时候不为null covertview的复用
3.调用getView方法的时候 convertView为空 infater调用个参数的 viewHolder的使用 减少findView的使用,保存引用
4. ViewHolder防错位 滑动之后 0变成10
5.设置listView的手势监听器 isfling会有大量视图产生 不需要开启线程
6.setFocusable 为 false 不可聚焦 listview的item可以选中
下面详细介绍:
第一点:
布局文件中,listview控件的高度一定不能使wrap_content
如果是的话会重复调用测量高度的方法
1.listView高度为match_parent
2.高度改为xxxdp.
第二点:
convertView用上,这个只要有一个不为null之后,其它的都不为null.
通过xml转换得到的view对象。
减少填充的调用次数。现在在一个常数集。
1.先写一个适配器
2.里面定义一个list,然后new,实例化
3.先一个追加的方法,可以追加也可以覆盖,也可以再写一个追加一条的方法。
第三点:
减少findViewById的时间,
用法:(1)通过外面定义一个类,里面声明item布局的那些控件。
(1)通过外面定义一个类,里面声明要找的控件的对象
private class ViewHolder {
public int position;
// 这个postiton代表真实的第几条数据如果一页10个,从0-9那下一页就是从10-18。
public TextView title;
public ImageView thumbnail;
}
(2)getview方法中,在convertview==null的条件中,生成viewHolder对象,把得到的控件对象,赋值给viewHolder的里面声明的属性,并把viewHolder作为tag属性赋值给view.即view.setTag(vh);
以上三点的代码如下:
private class MyAdapter extends BaseAdapter {
private List<String> datas;
public MyAdapter() {
datas = new ArrayList<String>();
}
public void addAll(List<String> data, boolean clear) {
if (data != null) {
if (clear) {
datas.clear();
}
datas.addAll(data);
}
}
public void add(String data) {
datas.add(data);
}
@Override
public int getCount() {
return datas.size();
}
@Override
public String getItem(int position) {
return datas.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
v = LayoutInflater.from(getApplicationContext()).inflate(
R.layout.item, parent, false);
ViewHolder vh = new ViewHolder();
vh.title = (TextView) v.findViewById(R.id.title);
vh.thumbnail = (ImageView) v.findViewById(R.id.thumbnail);
v.setTag(vh);
v.findViewById(R.id.btn).setFocusable(false);
}
ViewHolder vh = (ViewHolder) v.getTag();
vh.position = position;
String titleStr = getItem(position);
vh.title.setText(titleStr);
// 5.列表在甩动时,不用启动线程下载图片
if (!isFling) {
// new LoadImgTask(vh, position).equals("http://.....");
}
return v;
}
}
第四点:
错位
return之前设置好布局就不会错位,如果return之后才尝试设置布局。就会错位。
1.异步
2.如果listView保持静止。就不会错位。
利用position防止错位
每次看看现在的postion和构造时提供的位置是否相等,如果相等,就表示没变过。或者变了又回来了。则设置,否则不设置。
实现方法就是,异步下载图片的时候传一个当前的position,然后把这个值赋给异步里的一个属性,然后当下载完成的时候判断当前viewHolder的positon是不是跟你传入的position相等,如果相等表示是这个位置,就更新ui,否则不更新ui。
代码段:
// 异步下载图片
private class LoadImgTask extends AsyncTask<String, Void, Bitmap> {
private String url;
private ViewHolder vh;
private final int position;
// 4.利用position来防止错位
public LoadImgTask(ViewHolder vh, int position) {
this.vh = vh;
this.position = position;
}
@Override
protected Bitmap doInBackground(String... params) {
url = params[0];
// TODO downloading这里进行图片下载功能。
byte[] data = null;
// 返回解码后的bitmap
return BitmapFactory.decodeByteArray(data, 0, data.length);
}
// 这个方法是下载完成后调用。
@Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
if (result != null) {
// 这个position是开启线程的时候调用的position。这个vh是下载完成后vh的position,
// 因为vh是外部类的所有他的属性时刻变化着,当你调用的时候外面变动了,引用这个
// 对象的position也是现在的值。
if (position == vh.position) {
// 更新ui
vh.thumbnail.setImageBitmap(result);
}
}
}
}
第五点:
如果一下子从1滑到了最后,则这个是不需要起线程的,因为线程池里面的有限。所以抓住此状态。fling甩。设置监听setonScrollListener。
1.判断如果是甩动的状态,就不起线程。
isFling=(scrollState == OnScrollListener.SCROLL_STATE_FLING)
用法:
(1).给listView设置监听
定义标志位
private boolean isFling;
lv.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub
isFling = (scrollState == OnScrollListener.SCROLL_STATE_FLING);
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
}
});
(2) // 5.列表在甩动时,不用启动线程下载图片,判断如果没有甩动就开现场下载
if (!isFling) {
// 异步开启线程下载,构造里面传入vh,和position。
// new LoadImgTask(vh, position).equals("http://.....");
}
第六点:
listView放到了scrollView里面怎么滑动。
listView放了viewPager怎么滑动。
item里面放了button或者checkbox,则整个item不能点击了。
4.4已经修复了此bug.
为什么item不可点,是因为item里面的控件有可聚焦事件,所以外面的
item无法点击。我们可以让那些可聚焦的控件setFocusable(false)...(不可聚焦)
用法:item能实现点击的原理是:除了某个条件还有一个就是里面的控件不聚焦。
(1)例如item里面有button按钮,让控件不聚焦,
// 这是是防止让item里面的控件不聚焦。
v.findViewById(R.id.btn).setFocusable(false);
http://download.csdn.net/detail/liu13722785488/7840115