使用第三方类库加载图片碰到的问题

开发手机台项目中用户要求首页内容可以自定义显示,图片大致如下:

这不是一个列表吗?将每一行的封装成一个组件(使用了NoScrollGridView),使用列表展示就行了。下面讲述一下碰到的一些奇葩问题。

1.二级列表时UIL图片出现错位问题

当时整个APP图片加载都是使用的UIL(Univeral-Image-Loader),搜索了一下,网上有牛人说,在listview列表的图片加载中,涉及到组件的复用问题,给图片设置上tag,相关代码如下。

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

    //关键点,给imageview设置tag;
            holder.anchorPhoto.setTag(iconUrl);
            mImageLoader.loadImage(
            iconUrl,options,
//下面是UIL加载图片完成后的回调,类的详情,见下文
            new ImageLoadingListener(
            holder.anchorPhoto,defaultBitmap)));
        }
    public class ViewHolder {
        public ImageView anchorPhoto;
    }
}

public class ImageLoadingListener implements com.nostra13.universalimageloader.core.listener.ImageLoadingListener {
    private ImageView mView;
    private Bitmap mDefaultBitmap;
    public ImageLoadingListener(ImageView photo, Bitmap defaultBitmap) {
        this.mView = photo;
        this.mDefaultBitmap = defaultBitmap;
    }

    @Override
    public void onLoadingComplete(String arg0, View arg1, Bitmap arg2) {
//通过tag,确定是否展示图片。1.如果tag和ImageView对应,也就是ImageView在可视范围内(没有被重用,则加载图片;否则取消)
        if (arg0.equals(mView.getTag())) {
            mView.setImageBitmap(arg2);
        }
    }

}

这个方案在理论上无懈可击。但是仅仅在一级列表中展示(也就是布局中仅仅用ListView、没有ViewGroup的嵌套)没有问题。
曾经以为是虽然调用了这个方法,也有可能是listview没有进行及时刷新的问题。就在ImageLoadingListener ,定义一个回调接口,在listview中实现(直接调用notifyDataSetChange进行刷新页面),后来就出现了,刷新的死循环,结果就是在部分手机上出现了频繁闪屏。依然没有解决问题。

2.探索其他加载图片的组件

在网络上简单搜索了一下,现在在安卓端图片加载的组件呈现鼎足之势。下面简单描述一下其他两个(UIL上面提到了,在这里就不罗嗦了):

  • Picasso

可以实现图片的网络加载和本地缓存(普通的图片可以,但是我们公司平台上的图片只能实现在线加载)。

  • Volley

Google一个开源的项目,它的功能不仅仅局限于加载并缓存网络图片(sd卡缓存,需要自己进行添加),它最大的长处在于便捷的和服务器交互的方法(普通的图片可以,但是我们公司平台上的图片只能实现在线加载)。后来在一次无意中找到,“Volley中,通过网络获取来的数据其实都是字节流,Volley只是通过Response的Header信息来设置缓存记录的生命周期”,通过修改HttpHeaderParser.java中的parseCacheHeaders方法,实现了公司平台上网络图片的缓存。
默认保留一周,我的对该方法的修改如下:

  public static Cache.Entry parseCacheHeaders(NetworkResponse response) {
        final long weekInMill=7*24*3600*1000;
        final long nowInMill=System.currentTimeMillis();
        long now = System.currentTimeMillis();

        Map<String, String> headers = response.headers;

        long serverDate = 0;
        long lastModified = 0;
        long serverExpires = 0;
        long softExpire = 0;
        long finalExpire = 0;
        long maxAge = 0;
        long staleWhileRevalidate = 0;
        boolean hasCacheControl = false;
        boolean mustRevalidate = false;

        String serverEtag = null;
        String headerValue;

// headerValue = headers.get("Date");
// if (headerValue != null) {
// serverDate = parseDateAsEpoch(headerValue);
// }
        serverDate=now;
        headerValue = "max-age=15552000";
// headerValue = headers.get("Cache-Control");
        if (headerValue != null) {
            hasCacheControl = true;
            String[] tokens = headerValue.split(",");
            for (int i = 0; i < tokens.length; i++) {
                String token = tokens[i].trim();
                if (token.equals("no-cache") || token.equals("no-store")) {
                    return null;
                } else if (token.startsWith("max-age=")) {
                    try {
                        maxAge = Long.parseLong(token.substring(8));
                    } catch (Exception e) {
                    }
                } else if (token.startsWith("stale-while-revalidate=")) {
                    try {
                        staleWhileRevalidate = Long.parseLong(token.substring(23));
                    } catch (Exception e) {
                    }
                } else if (token.equals("must-revalidate") || token.equals("proxy-revalidate")) {
                    mustRevalidate = true;
                }
            }
        }

// headerValue = headers.get("Expires");
// if (headerValue != null) {
            serverExpires =nowInMill+weekInMill;
// serverExpires = parseDateAsEpoch(headerValue);
// }

        headerValue = headers.get("Last-Modified");
        if (headerValue != null) {
            lastModified = parseDateAsEpoch(headerValue);
        }
        serverEtag = headers.get("ETag");

        // Cache-Control takes precedence over an Expires header, even if both exist and Expires
        // is more restrictive.
        if (hasCacheControl) {
            softExpire = now + maxAge * 1000;
            finalExpire = mustRevalidate
                    ? softExpire
                    : softExpire + staleWhileRevalidate * 1000;
        } else if (serverDate > 0 && serverExpires >= serverDate) {
            // Default semantic for Expire header in HTTP specification is softExpire.
            softExpire = now + (serverExpires - serverDate);
            finalExpire = softExpire;
        }

        Cache.Entry entry = new Cache.Entry();
        entry.data = response.data;
        entry.etag = serverEtag;
        entry.softTtl = softExpire;
        entry.ttl = finalExpire;
        entry.serverDate = serverDate;
        entry.lastModified = lastModified;
        entry.responseHeaders = headers;

        return entry;
    }

你可能感兴趣的:(图片加载)