继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Android的listview使用之4,优化

万千封印
关注TA
已关注
手记 90
粉丝 13
获赞 64

前面我们的问题是,当Listview加载数据量比较大时,会出现OOM异常,因为每个item都占了一块内存,item达到一定量的时候,内存就被占满了,导致了内存溢出,那么 我们就要对Listview来进行优化,因为我们的屏幕能显示的item条数是有限的,所以我们划出屏幕的item就可以回收给下一个item来使用,只需要修改里面的数据就可以了,思路就是这样,然后我们看getView方法里面有一个参数,就是第二个参数 View类型的convertView,这个就是表示我们刚刚划出屏幕的item,当item1滚出屏幕,并且一个新的项目从屏幕地段上来时,ListView再请求一个type1视图。convertView此时不是空值了,它的值是item1.你只需要设定新的数据返回convertView,不必重新创建一个视图。这样直接使用convertView从而减少了很不不必要view的创建。这就是我们优化Listview的思路,我们用一个类,包含item

里面的每个控件,作为一个对象,当convertView为空的时候去findViewByid,不为空时,直接拿到convertView里面的控件,修改数据就可以了,下面是优化过后的适配器代码

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder=null;
    //当convertView为空的时候,findViewByid赋值给ViewHolder
    if (null==convertView) {
        holder=new ViewHolder();
        convertView = mInflater.inflate(R.layout.my_listview_item, null);//通过mInflater来加载布局
        holder.iv = (ImageView) convertView.findViewById(R.id.iv);//找到对应的控件
        //把holder设置为convertView的标记
        convertView.setTag(holder);
    }else {
        //当convertView不为空的时候,从convertView拿到标记,也就是holder
        holder = (ViewHolder) convertView.getTag();
    }
    //拿到holder对象里面的控件进行数据加载
    MyAsyncTask myAsyncTask = new MyAsyncTask(holder.iv);
    myAsyncTask.execute(list.get(position));
    return convertView;
}

/**
 * viewHolder保存每一个item里面的控件
 */
class ViewHolder{
    ImageView iv;//每个item的控件
}

这时候我们就避免了数据量过多引起的OOM异常,但我们会发现,会出现图片错位,过一会又跳到显示正确的图片的情况,这是因为我们是复用的上一个划出屏幕的控件里面包含有数据,新的数据加载进入需要网络,会消耗时间,所以会出现前面的图片显示在控件上,过一会又显示新的图片的问题,所以现在我们需要解决图片的错位的问题,我们的思路也是给TmageView来设置一个标记,当我们当前的标记不等于我们预设的标记的时候,就显示我们预设的图片,防止错位。下面是最终代码,

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder=null;
    //当convertView为空的时候,findViewByid赋值给ViewHolder
    if (null==convertView) {
        holder=new ViewHolder();
        convertView = mInflater.inflate(R.layout.my_listview_item, null);//通过mInflater来加载布局
        holder.iv = (ImageView) convertView.findViewById(R.id.iv);//找到对应的控件
        //把holder设置为convertView的标记
        convertView.setTag(holder);
    }else {
        //当convertView不为空的时候,从convertView拿到标记,也就是holder
        holder = (ViewHolder) convertView.getTag();
    }
    String url=list.get(position);
    //拿到标记
    String tag = (String) holder.iv.getTag();
    //当标记不一样的时候,显示默认的图片
    if ( url!=tag) {
        // 预设一个图片
        holder.iv.setImageResource(R.mipmap.ic_launcher);
        //设置标记tag
        holder.iv.setTag(url);
    }
    //拿到holder对象里面的控件进行数据加载
    MyAsyncTask myAsyncTask = new MyAsyncTask(holder.iv);
    myAsyncTask.execute(list.get(position));
    return convertView;
}

这样就解决了错位的问题,看效果

5bb81bdc0001dcad04550840.jpg

当图片还没有加载的时候,就显示默认的图片,加载完后,再显示,好了,这次的优化就到这,下次再见咯

原文链接:http://www.apkbus.com/blog-843025-61567.html

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP