关于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
版权声明:本文为博主原创文章,未经博主允许不得转载。

多线程面试题

1) 什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。程序员可以通过它进行多处理器编程,你可以使用多线程对运算密集型任务提速。比如,如果一个线程完成...

GridView图片加载重复的正确解决方法

GridView图片加载重复的正确解决方法: public View getView(int position, View convertView, ViewGroup parent) { ...

解决由于异步加载和getview的混用导致图片错位

最近开发文件浏览列表一块,其中通过接口查询当前目录下的所有文件和文件夹,对于文件夹我们就显示文件夹的一些属性:图像是文件夹,然后可以进入他的下级目录;但对于文件的话我们就需要根据不同的类型,例如图片和...

getView顺序加载显示图片

在getView中加载缩略图,按照顺序一张一张的显示 前提:使用的是HTTP请求,访问的是一个DVR中的文件(图片),这里的DVR猜测不支持并发,不是访问HTTP的服务器。 过程:...

Android加载网络图片(双缓存,无错位,无闪烁,无重复)

转载来自:http://avatar.csdn.net/B/D/2/1_a79412906.jpg
  • hyq912
  • hyq912
  • 2014年08月28日 16:05
  • 855

从源码角度看Volley中图片加载ImageLoader的重复URL过滤功能

在android开发中,volley算的上是一个比较出名的开源库,首先是因为它是google官方出品的,有亲儿子的意思。其次,它功能强大,它不仅能够高效的完成高并发且数据量小的网络请求,还附带有自己的...

Android Universal Image Loader加载 ListView 滑动过程中图片显示重复错位闪烁问题

项目使用uil加载listview图片时,出现过一次头像加载错了的问题, 之后在一篇博客上看到一种解决方案,可以借鉴 http://www.trinea.cn/android/android-list...

GridView 中getview方法position 0 加载多次问题

int mCount = 0;         public View getView(int position, View convertView, ViewGroup parent) {     ...

gridview position =0多次调用getView, 如果有异步加载,那会导致程序效率低,并且导致position=0的控件显示有问题

问题:gridview  position =0多次调用getView, 如果有异步加载,那会导致程序效率低,并且导致position=0的控件显示有问题。 查找了些资料,大概是因为gridview需...
  • juishi
  • juishi
  • 2016年03月05日 23:05
  • 925
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:关于getView中图片重复加载
举报原因:
原因补充:

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