android_ListView优化

ListView 优化
ListView的显示机制:
listview会先通过onMeasure()方法计算出一个手机屏幕能展示多少个item
假如你有1000条数据,但是屏幕只能显示10条,那么当你第一次加载显示的时候,会先创建10个View(调用10次getView方法),1-10,当你拖动Listview,使1隐藏而11显示的时候,系统会自动把填充1的View传递过来
当我们固定listview的高度时(fill_parent或直接固定高度),那么listview很容易就能计算(onMeasure方法)出容器内可以显示多少行。但如果我们使用了“wrap_content”,只有在屏幕内控件完全加载后才知道到底能显示多少行数据时,ListView自身便会做一些尝试性计算。


ListView优化方式:
1.1 内存空间优化(ConvertView)
优化原理:重用缓存convertView传递给getView()方法来避免填充不必要的视图
Q:为什么要convertView复用?
ListView中的每一个Item显示都需要Adapter调用一次getView的方法,这个方法会传入一个convertView的参数,返回的View就是这个Item显示的View。
如果当Item的数量足够大,再为每一个Item都创建一个View对象,必将占用很多内存,创建View对象(mInflater.inflate(R.layout.lv_item, null);从xml中生成View,这是属于IO操作)也是耗时操作,所以必将影响性能。Android提供了一个叫做Recycler(反复循环器)的构件,就是当ListView的Item从上方滚出屏幕视角之外,对应Item的View会被缓存到Recycler中,相应的会从下方生成一个Item,而此时调用的getView中的convertView参数就是滚出屏幕的Item的View,所以说如果能重用这个convertView,就会大大改善性能。


&convertView复用使用代码说明:
View view = null;
if(convertView == null){
LayoutInflater inflater = LayoutInflater.from(context);
view = inflater.inflate(R.layout.items, null);
}else{
//如果convertView不为空,说明该view之前加载进来过,所以直接将其赋 给view,即反复使用,避免再创建新的view浪费资源
view = convertView;
}
TextView tv = (TextView) view.findViewById(R.id.textView1);
tv.setText(getList().get(position));
System.out.println("position-->" + position);
return view;

简单的写就是:
if (convertView==null ) {
convertView=LayoutInflater.from(context).inflate(layout, null);
//其他代码
}

1.2 运行时间优化(ViewHolder)
优化原理:使用ViewHolder模式来避免没有必要的调用findViewById():因为太多的findViewById也会影响性能

I.写一个ViewHolder类
static class ViewHolder {
TextView tv;
ImageView iv;
}
II.使用ViewHolder
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
LayoutInflater mLayoutInflater = LayoutInflater.from(context);
convertView = mLayoutInflater.inflate(layout, null);
viewHolder = new ViewHolder();
convertView.setTag(viewHolder);
viewHolder.tv = (TextView) convertView.findViewById(R.id.tv);
viewHolder.iv = (ImageView) convertView.findViewById(R.id.iv);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
return convertView; }

1.3异步加载图片出错
为了防止ListView异步加载图片错位、重复、闪烁等情况,我们需要给ImageView设置一个Tag,这个Tag中设置的是图片的url,在异步加载完成时我们可以比较下图片的url与当前行Item的标识是否一致,一致则显示,否则不做处理即可。方法步骤:
1.给当前ImageView对象设置标识
viewholder.iv.setTag(img_url);

2.给当前ImageView设置一个默认的值(因为控件是复用的, 用完之后其中的值还存在,所以需要清洗下,这里可以给随意给一张默认的图片)
viewholder.iv.setImageResource(R.drawable.ic_launcher);

3.在异步类里面判断tag值和图片地址是否相等,若相等,则说明该控件在当前的位置所需要展示的图片 是对的,就可以直接展示出来.这里有两种方法实现:
第一种在异步线程onPostExecute()方法里设置:
protected void onPostExecute(Bitmap result) {
// TODO Auto-generated method stub
super.onPostExecute(result);

// 防止图片错位,判断下tag值和图片地址是否相等
if (result != null && img_url.equals(iv.getTag())) {
// 设置图片
iv.setImageBitmap(result);
}
}

第二种在:在继承BaseAdapter类getView()方法进行设置:
//设置标识
viewHolder.iv.setTag(url);
//设置默认图片占位
viewHolder.iv.setImageResource(R.drawable.ic_launcher);
MyBitmapTask task=new MyBitmapTask();
task.execute(url);
viewHolder.tv.setText(str);
task.setBitmapInterface(new MyBitmapInterface() {
@Override
public void getBitmap(Bitmap bmp) {
if (bmp!=null&& viewHolder.iv.getTag().equals(url)) {
viewHolder.iv.setImageBitmap(bmp);
}
}
});

--------------------------------------------------------------------------------------------------------


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值