模拟volley写小型图片下载及缓存框架

写SDK的时候,碰到一个小的需求,银行的小图标需要访问服务器下载,并且要缓存在本地。
因为SDK项目中银行图标类似图片并不是很多,如果使用第三方框架的话太大,大材小用,而且类似加载图片的第三方很多,如果SDK接入了volley,但是接入我们SDK的app却使用了picasso,会导致同样功能代码的重复,方法数也容易超标。
所以就要自己写一个小的框架,简要描述就是给出图片url,第一次进行网络访问,并缓存在本地(包括内存和硬盘缓存)。后续都可以从本地读取。(不处理服务器给出的头部,例如有效期等等)。
代码:
git clone https://github.com/LxxCaroline/MyApplication.git

该小框架是主要模仿volley而写的,有类似的几个class,包括RequestQueue, ImageRequest, NetworkDispatcher, CacheDispatcher, HttpEngine(类似HurlStack), ImageCache, NetworkImageView

ImageRequest主要是封装了请求,包括url,listener,bitmap,isCanceled,tracer(Arraylist主要是记录该request流程的走向)
RequestQueue是中央处理枢纽,ImageRequest交给RequestQueue来处理,由RequestQueue开启网络线程NetworkDispatcher和缓存线程CacheDispatcher来处理一些将要处理的ImageRequest。一般ImageRequest是先通过CacheDispatcher来获取,如果获取不到,则通过NetworkDispatcher来获取,之后再写入到Cache中。ImageCache主要是来读写Cache的,这里用到了LruCache和DiskLruCache。
NetworkImageView是专门用来加载图片的,HttpEngine就是真正访问网络的地方。

在RequestQueue中有几个重要的变量:

private Map<String, Queue< ImageRequest >> mWaitingRequests;
private PriorityBlockingQueue<ImageRequest> mNetworkQueue;
private PriorityBlockingQueue<ImageRequest> mCacheQueue;

第一个变量是记录当往RequestQueue中加入request的时候,先检测是否有相同url的request,如果有,则将该request加入到相同url的queue中去,这样当第一个相同url的request返回的时候,可以把结果分享给queue中的request。
第二个参数是维护将要被网络访问的request队列。
第三个参数是维护将要访问Cache的request队列。
刚刚说到RequestQueue中会开启网络和cache线程,一般来说cache访问会很快,所以只用开一个cache线程。network比较慢,所以如果你项目中图片访问量大的话,则需要多开几个线程,如果图片访问量不大的话,开一至两个线程就可以了。
一个cache线程的话,都从requestQueue的mCacheQueue中取,而多个network线程的话,都从requestQueue的mNetworkQueue中取(所有线程共享)。
priorityBlockingQueue是无界队列,并且具有优先级,可以以一定的顺序去读取request,至于如何定优先级,用户可以自己定义,例如先来后到,或给某些request一些高的优先级。

在NetworkImageView中,拿到bitmap后,需要给自己setImageBitmap,但是注意,需要在主线程中进行。
原来NetworkImageView的代码:

private ImageRequest request = null;
private RequestQueue queue;

public void setRequestQueue(RequestQueue queue){
    this.queue = queue;
}

public void setImageUrl(String url) {
    if (request != null) {
        request.setListener(null);
    }
    request = new ImageRequest(url);
    request.setListener(this);
    queue.addRequest(request);
}

@Override
public void onResponse(final Bitmap bitmap) {
    Log.d("RequestQueue-View", "setBitmap " + (bitmap != null));
    post(new Runnable() {
        @Override
        public void run() {
            Log.d("RequestQueue-View", "setBitmap succ");
            setImageBitmap(bitmap);
        }
    });
}

@Override
protected void onDetachedFromWindow() {
    if (request != null) {
        request.isCanceled = true;
        request.setListener(null);
    }
    super.onDetachedFromWindow();
}

发现在onResponse函数中,只打印了第一个log,第二个却没打印(也就是说runnable中的内容都没有执行),导致图片未显示。。。
后来查到post(runnable)在view没有被attach到window之前,是没有效果的,后来代码改成如下:

public void setImageUrl(String url) {
    if (request != null) {
        request.setListener(null);
    }
    request = new ImageRequest(url);
    request.setListener(this);
    if (isAttachedToWindow()) {
        queue.addRequest(request);
    }
}

@Override
protected void onAttachedToWindow() {
    super.onAttachedToWindow();
    if (request != null) {
        queue.addRequest(request);
    }
}

接下来说下DiskLruCache,这个是硬盘缓存技术,这个类的代码需从网上下,并非google撰写,但得到官方认可。具体说明可以看这篇文章:
Android DiskLruCache缓存完全解析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值