关于getView中图片重复加载

原创 2016年05月31日 20:51:13

在ListView或GridView中,经常会出现getView反复调用的问题。究其原因,是视图进行绘制前多次onMeasure的结果。
要解决这个问题,就要避免父视图反复测量以适应整个布局,尽量避免使用wrap_content属性。

普通的getView反复调用问题并不会有太大的影响,会产生影响的往往是在getView中实行的操作,比如在getView中加载图片之类的。

例如,我要在ScrollView中嵌入一个GridView中,然后在GridView显示图片,为了避免一些奇怪的问题产生(比如滑动冲突或者干脆没法滑动),就要覆写onMeasure方法使其自适应:

public class AlbumGridView extends GridView {

    public AlbumGridView(Context context) {
        super(context);
    }

    public AlbumGridView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public AlbumGridView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int height =MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, height);
    }
}

我将AlbumGridView放入ScrollView中,然后用AlbumGridView加载图片,得到以下Log:

05-31 08:21:56.729 1689-1689/com.xter.picbrowser W/load: file:///storage/emulated/0/Download/img/img (4).jpg
05-31 08:21:56.729 1689-1689/com.xter.picbrowser W/load: file:///storage/emulated/0/Download/img/img (4).jpg
05-31 08:21:56.730 1689-1689/com.xter.picbrowser W/load: file:///storage/emulated/0/Download/img/img (4).jpg
05-31 08:21:56.730 1689-1689/com.xter.picbrowser W/load: file:///storage/emulated/0/Download/img/img (3).jpg
05-31 08:21:56.731 1689-1689/com.xter.picbrowser W/load: file:///storage/emulated/0/Download/img/img (2).jpg
05-31 08:21:56.734 1689-1689/com.xter.picbrowser W/load: file:///storage/emulated/0/Download/img/img (1).jpg
05-31 08:21:56.800 1689-1689/com.xter.picbrowser W/load: file:///storage/emulated/0/Download/img/img (4).jpg
05-31 08:21:56.800 1689-1689/com.xter.picbrowser W/load: file:///storage/emulated/0/Download/img/img (4).jpg
05-31 08:21:56.817 1689-1689/com.xter.picbrowser W/load: file:///storage/emulated/0/Download/img/img (4).jpg
05-31 08:21:56.817 1689-1689/com.xter.picbrowser W/load: file:///storage/emulated/0/Download/img/img (4).jpg
05-31 08:21:56.850 1689-1689/com.xter.picbrowser W/load: file:///storage/emulated/0/Download/img/img (4).jpg
05-31 08:21:56.851 1689-1689/com.xter.picbrowser W/load: file:///storage/emulated/0/Download/img/img (4).jpg
05-31 08:21:56.878 1689-1689/com.xter.picbrowser W/load: file:///storage/emulated/0/Download/img/img (4).jpg
05-31 08:21:56.879 1689-1689/com.xter.picbrowser W/load: file:///storage/emulated/0/Download/img/img (4).jpg

可以看到,getView在重复调用,且第一张图片img (4).jpg更是反复调用了11次。总共4张图片,调用了14次,试验多次,第一张图片总是会反复调用多次——单纯调用getView影响并不大,但因为是图片加载,要在getView中根据uri加载图片,这样问题就大了。
于是改写AlbumGridView并在getView中判断是否在测量中,如果在测量中,就先不加载图片,否则就开始加载图片,这样一来会节省很多资源:

public class AlbumGridView extends GridView {
    public boolean isOnMeasure;

    public AlbumGridView(Context context) {
        super(context);
    }

    public AlbumGridView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public AlbumGridView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        isOnMeasure = true;
        int height = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, height);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        isOnMeasure = false;
        super.onLayout(changed, l, t, r, b);
    }

    public boolean isOnMeasure() {
        return isOnMeasure;
    }

加一个isOnMeasure标记以判断视图当前状态;

public class PhotosAdapter extends BaseAdapter {

    ......

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view;
        if (convertView == null) {
            view = layoutInflater.inflate(R.layout.item, parent, false);//inflate item
        } else {
            view = convertView;
        }

        if (parent instanceof AlbumGridView) {
            if (((AlbumGridView) parent).isOnMeasure()) {
                return view;
            } else {
                Log.w("load",""+url);
                //加载图片
            }
        }
        return view;
    }

}

这样一来,getView其实还是反复在调用,但是图片加载却不会再反复加载了。其Log如下:

05-31 08:40:54.750 1689-1689/com.xter.picbrowser W/load: file:///storage/emulated/0/Download/img/img (4).jpg
05-31 08:40:54.751 1689-1689/com.xter.picbrowser W/load: file:///storage/emulated/0/Download/img/img (3).jpg
05-31 08:40:54.751 1689-1689/com.xter.picbrowser W/load: file:///storage/emulated/0/Download/img/img (2).jpg
05-31 08:40:54.752 1689-1689/com.xter.picbrowser W/load: file:///storage/emulated/0/Download/img/img (1).jpg
版权声明:本文为博主原创文章,未经博主允许不得转载。

ListView中getView()的原理

ListView 和 Adapter 的基础 工作原理: ListView 针对List中每个item,要求 adapter “给我一个视图” (getView)。 一个新的视图被返回并显示 如果...
  • DayDayPlayPhone
  • DayDayPlayPhone
  • 2016年09月14日 17:05
  • 1567

Adapter的getView方法详解

BaseAdapter就Android应用程序中经常用到的基础数据适配器,它的主要用途是将一组数据传到像ListView、Spinner、Gallery及GridView等UI显示组件,它是继承自接口...
  • Yelbosh
  • Yelbosh
  • 2012年08月05日 11:55
  • 63344

listview的getview的参数解析

工作原理: ListView 针对List中每个item,要求 adapter “给我一个视图” (getView)。一个新的视图被返回并显示 如果我们有上亿个项目要显示怎么办?为每个项目...
  • kongzhichen
  • kongzhichen
  • 2013年08月31日 11:06
  • 9946

android Listview的getView和convertview原理解析(三)

以前一直在用BaseAdapter,对于其中的getview方法的重写一直不太清楚。今天终于得以有空来探究它的详细机制。 下面先讲讲我遇到的几个问题: 一.View getview(int pos...
  • u011494050
  • u011494050
  • 2014年05月10日 15:26
  • 2398

ListView加载混乱以及getView重复调用问题

1:因为复用item造成数据混乱 解决方法:http://www.trinea.cn/android/android-listview-display-error-image-when-scroll...
  • u010513497
  • u010513497
  • 2017年03月20日 17:06
  • 169

ListView getview()重复被调用

重写的listviewadapter中,在getView()方法中,打印语句时,相同的position打印了多次,修改方法: 将布局文件中ListView的高度改为“fill_parent”...
  • rongwenbin
  • rongwenbin
  • 2015年11月12日 16:34
  • 422

android: BaseAdapter的getview方法会多次重复调用

BaseAdapter的getview方法会多次重复调用 Q: 在使用ListView和其他控件在一个界面时,发现getview方法被重复调用了5次,不是从item0到item4,而是生成...
  • aree
  • aree
  • 2014年02月11日 17:19
  • 2163

彻底解决listview,gridview的getview多次调用问题

listview,gridview,有时候getview会调用多次,特别是把listview放在viewpager中,很容易卡顿 网上的方法往往只是说,把listview的height固定住...
  • ksr12333
  • ksr12333
  • 2014年01月17日 14:59
  • 18279

ListView设置adapter时getView被多次调用

今天在做项目的时候,发现ListView在高度为wrap_content时,adater中的getView方法居然被调用了三次,于是在网上搜索 发现也有网友与我碰到的问题相同,但有的只是说把wrap...
  • jonloong
  • jonloong
  • 2015年12月16日 11:49
  • 3199

ListView和GridView重复调用getView的解决方法

场景:文件管理加载大容量磁盘过程中,列表浏览和平铺浏览按遥控器快速移动光标,概率性会有卡顿现象。   分析原因:列表浏览使用的是ListView,平铺浏览使用的是GridView, 可能是重复调用了g...
  • csszhw0715
  • csszhw0715
  • 2017年01月16日 15:07
  • 593
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:关于getView中图片重复加载
举报原因:
原因补充:

(最多只允许输入30个字)