volley 缓存清理不干净

公司做的框架使用的volley,这里做一下图片缓存的说明,实现储存图片,获取图片,清理单个图片缓存和清理全部图片缓存,但是在使用的过程中,发现清理了缓存,图片缓存依然存在,为什么呢,通过查看源码,发现,volley不仅有内存存储,还有sd卡存储,只是这个是封装起来的,需要自己去找到,并进行操作

使用步骤:

1.首先建立一个队列:

private RequestQueue mRequestQueue;

if (mRequestQueue == null) {
    mRequestQueue = Volley.newRequestQueue(context);
}
2.使用json作为参数做网络请求

 

 JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.POST, url, jsonParams,
                new Response.Listener<JSONObject>() {

                    @Override
                    public void onResponse(JSONObject response) {
                       
                }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
              
}

        }) {
            //添加请求头
            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                Map<String, String> headers = new HashMap<String, String>();
                headers.put("Token", Token.getToken());
                return headers;
            }
        };
3.将这个jsonObjectRequest()放进队列

mRequestQueue.add(jsonObjReq);
调用的时候,直接给jsonObject传对应的参数即可


这里需要加载图片的方法是:

1.首先建立一个内存类,去继承LruCache  ,

public class BitMapCache implements ImageLoader.ImageCache {
    private LruCache<String, Bitmap> cache;

    private static BitMapCache bitMapCache;

    private BitMapCache() {
        int maxMemory = (int) Runtime.getRuntime().maxMemory();
        cache = new LruCache<String, Bitmap>(8 * 1024 * 1024) {
            @Override
            protected int sizeOf(String key, Bitmap bitmap) {
                return bitmap.getRowBytes() * bitmap.getHeight();
            }
        };
    }

    public static BitMapCache getInstance() {
        if (bitMapCache == null) {
            bitMapCache = new BitMapCache();
        }
        return bitMapCache;
    }

    @Override
    public Bitmap getBitmap(String url) {
        return cache.get(url);
    }

    @Override
    public void putBitmap(String url, Bitmap bitmap) {
        cache.put(url, bitmap);
    }

    public int getBitmapCacheSize() {
        return cache.size();
    }

    public void removeBitmapSize() {
        cache.evictAll();
    }

    public void clearBitmap(String url, int maxWidth, int maxHeight) {
        cache.remove(getCacheKey(url, maxWidth, maxHeight));
    }

    //同ImageLoader里私有方法
    private static String getCacheKey(String url, int maxWidth, int maxHeight) {
        return (new StringBuilder(url.length() + 12)).append("#W").append(maxWidth).append("#H").append(maxHeight).append(url).toString();
    }
这个缓存图片类里面实现了储存图片,获取图片,清理单个图片缓存和清理全部图片缓存,但是在使用的过程中,发现清理了缓存,图片缓存依然存在,为什么呢,通过查看源码,发现,volley不仅有内存存储,还有sd卡存储,只是这个是封装起来的,需要自己去找到,并进行操作

2.将内存缓存放进Imageloader,在实例化队列后,紧跟着实例化Imageloader,并设置了内存缓存大小

if (mImageLoader == null) {
    mImageLoader = new ImageLoader(mRequestQueue, BitMapCache.getInstance());
}
3.实现将图片显示的方法


public void diaplayHeadImage(Context context, String url, final ImageView imageView, final int width, int height) {
    ImageLoader.ImageListener listener = new ImageLoader.ImageListener() {
        @Override
        public void onResponse(ImageLoader.ImageContainer response, boolean isImmediate) {
            if (response.getBitmap() != null) {
                Bitmap bm = response.getBitmap();
                if (width > 0) {
                    int bmWidth = bm.getWidth();
                    int bmHeight = bm.getHeight();
                    float scale = (float) width / bmWidth;
                    Matrix matrix = new Matrix();
                    matrix.postScale(scale, scale);
                    // 得到新的图片
                    bm = Bitmap.createBitmap(bm, 0, 0, bmWidth, bmHeight, matrix, true);
                }
                if (imageView.getTag() == null) {
                    imageView.setImageBitmap(bm);
                } else if (response.getRequestUrl().contains(imageView.getTag().toString())) {
                    imageView.setImageBitmap(bm);
                }
            } else {
                //set error image
                imageView.setImageResource(R.mipmap.img_default);
            }
        }

        @Override
        public void onErrorResponse(VolleyError volleyError) {
            //set error image
            imageView.setImageResource(R.mipmap.img_default);
        }
    };
    //有网再清理缓存
    if (Utils.IsNetworkAvailble(context)) {
        //清理图片缓存,内存缓存和磁盘缓存
        BitMapCache.getInstance().clearBitmap(url, 0, 0);
        mRequestQueue.getCache().remove(url);
        //  mRequestQueue.getCache().clear();
    }

    if (width != 0 || height != 0) {
        //指定图片允许的最大宽度和高度
        mImageLoader.get(url, listener, width, height);
    } else {
        mImageLoader.get(url, listener);
    }
}
4.这里明显没有存储到内存卡的步骤,那么图片是什么存储到内存卡的,点击
mImageLoader.get进源码

public ImageLoader.ImageContainer get(String requestUrl, ImageLoader.ImageListener imageListener, int maxWidth, int maxHeight) {
    this.throwIfNotOnMainThread();
    final String cacheKey = getCacheKey(requestUrl, maxWidth, maxHeight);
    Bitmap cachedBitmap = this.mCache.getBitmap(cacheKey);
    ImageLoader.ImageContainer imageContainer;
    if(cachedBitmap != null) {
        imageContainer = new ImageLoader.ImageContainer(cachedBitmap, requestUrl, (String)null, (ImageLoader.ImageListener)null);
        imageListener.onResponse(imageContainer, true);
        return imageContainer;
    } else {
        imageContainer = new ImageLoader.ImageContainer((Bitmap)null, requestUrl, cacheKey, imageListener);
        imageListener.onResponse(imageContainer, true);
        ImageLoader.BatchedImageRequest request = (ImageLoader.BatchedImageRequest)this.mInFlightRequests.get(cacheKey);
        if(request != null) {
            request.addContainer(imageContainer);
            return imageContainer;
        } else {
            ImageRequest newRequest = new ImageRequest(requestUrl, new Listener() {
                public void onResponse(Bitmap response) {
                    ImageLoader.this.onGetImageSuccess(cacheKey, response);
                }
            }, maxWidth, maxHeight, Config.RGB_565, new ErrorListener() {
                public void onErrorResponse(VolleyError error) {
                    ImageLoader.this.onGetImageError(cacheKey, error);
                }
            });
            this.mRequestQueue.add(newRequest);
            this.mInFlightRequests.put(cacheKey, new ImageLoader.BatchedImageRequest(newRequest, imageContainer));
            return imageContainer;
        }
    }
}

没有找到,但是发现了即使
cachedBitmap==null和网络断开的情况下,仍然会有图片展示,所以查看这里肯定走了弯路,那就从开头再找,发现在 
mRequestQueue = Volley.newRequestQueue(context);这里点进去 Volley类

public class Volley {
    private static final String DEFAULT_CACHE_DIR = "volley";

    public Volley() {
    }

    public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
        File cacheDir = new File(context.getCacheDir(), "volley");
        String userAgent = "volley/0";

        try {
            String network = context.getPackageName();
            PackageInfo queue = context.getPackageManager().getPackageInfo(network, 0);
            userAgent = network + "/" + queue.versionCode;
        } catch (NameNotFoundException var6) {
            ;
        }

        if(stack == null) {
            if(VERSION.SDK_INT >= 9) {
                stack = new HurlStack();
            } else {
                stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
            }
        }

        BasicNetwork network1 = new BasicNetwork((HttpStack)stack);
        RequestQueue queue1 = new RequestQueue(new DiskBasedCache(cacheDir), network1);
        queue1.start();
        return queue1;
    }

    public static RequestQueue newRequestQueue(Context context) {
        return newRequestQueue(context, (HttpStack)null);
    }
}
蓝色字体显示,在new队列的时候,里面出现个缓存  DiskBasedCache(cacheDir)类,觉得自己找到了方向,进入这个类

public class DiskBasedCache implements Cache {
    private final Map<String, DiskBasedCache.CacheHeader> mEntries;
    private long mTotalSize;
    private final File mRootDirectory;
    private final int mMaxCacheSizeInBytes;
    private static final int DEFAULT_DISK_USAGE_BYTES = 5242880;
    private static final float HYSTERESIS_FACTOR = 0.9F;
    private static final int CACHE_VERSION = 2;

    public DiskBasedCache(File rootDirectory, int maxCacheSizeInBytes) {
        this.mEntries = new LinkedHashMap(16, 0.75F, true);
        this.mTotalSize = 0L;
        this.mRootDirectory = rootDirectory;
        this.mMaxCacheSizeInBytes = maxCacheSizeInBytes;
    }

    public DiskBasedCache(File rootDirectory) {
        this(rootDirectory, 5242880);
    }

    public synchronized void clear() {
        File[] files = this.mRootDirectory.listFiles();
        if(files != null) {
            File[] var5 = files;
            int var4 = files.length;

            for(int var3 = 0; var3 < var4; ++var3) {
                File file = var5[var3];
                file.delete();
            }
        }

        this.mEntries.clear();
        this.mTotalSize = 0L;
        VolleyLog.d("Cache cleared.", new Object[0]);
    }

    public synchronized Entry get(String key) {
        DiskBasedCache.CacheHeader entry = (DiskBasedCache.CacheHeader)this.mEntries.get(key);
        if(entry == null) {
            return null;
        } else {
            File file = this.getFileForKey(key);
            DiskBasedCache.CountingInputStream cis = null;

            try {
                cis = new DiskBasedCache.CountingInputStream(new FileInputStream(file), (DiskBasedCache.CountingInputStream)null);
                DiskBasedCache.CacheHeader.readHeader(cis);
                byte[] e = streamToBytes(cis, (int)(file.length() - (long)cis.bytesRead));
                Entry var7 = entry.toCacheEntry(e);
                return var7;
            } catch (IOException var15) {
                VolleyLog.d("%s: %s", new Object[]{file.getAbsolutePath(), var15.toString()});
                this.remove(key);
            } finally {
                if(cis != null) {
                    try {
                        cis.close();
                    } catch (IOException var14) {
                        return null;
                    }
                }

            }

            return null;
        }
    }

    public synchronized void initialize() {
        if(!this.mRootDirectory.exists()) {
            if(!this.mRootDirectory.mkdirs()) {
                VolleyLog.e("Unable to create cache dir %s", new Object[]{this.mRootDirectory.getAbsolutePath()});
            }

        } else {
            File[] files = this.mRootDirectory.listFiles();
            if(files != null) {
                File[] var5 = files;
                int var4 = files.length;

                for(int var3 = 0; var3 < var4; ++var3) {
                    File file = var5[var3];
                    FileInputStream fis = null;

                    try {
                        fis = new FileInputStream(file);
                        DiskBasedCache.CacheHeader e = DiskBasedCache.CacheHeader.readHeader(fis);
                        e.size = file.length();
                        this.putEntry(e.key, e);
                    } catch (IOException var16) {
                        if(file != null) {
                            file.delete();
                        }
                    } finally {
                        try {
                            if(fis != null) {
                                fis.close();
                            }
                        } catch (IOException var15) {
                            ;
                        }

                    }
                }

            }
        }
    }

    public synchronized void invalidate(String key, boolean fullExpire) {
        Entry entry = this.get(key);
        if(entry != null) {
            entry.softTtl = 0L;
            if(fullExpire) {
                entry.ttl = 0L;
            }

            this.put(key, entry);
        }

    }

    public synchronized void put(String key, Entry entry) {
        this.pruneIfNeeded(entry.data.length);
        File file = this.getFileForKey(key);

        try {
            FileOutputStream deleted1 = new FileOutputStream(file);
            DiskBasedCache.CacheHeader e = new DiskBasedCache.CacheHeader(key, entry);
            e.writeHeader(deleted1);
            deleted1.write(entry.data);
            deleted1.close();
            this.putEntry(key, e);
        } catch (IOException var6) {
            boolean deleted = file.delete();
            if(!deleted) {
                VolleyLog.d("Could not clean up file %s", new Object[]{file.getAbsolutePath()});
            }

        }
    }

    public synchronized void remove(String key) {
        boolean deleted = this.getFileForKey(key).delete();
        this.removeEntry(key);
        if(!deleted) {
            VolleyLog.d("Could not delete cache entry for key=%s, filename=%s", new Object[]{key, this.getFilenameForKey(key)});
        }

    }

    private String getFilenameForKey(String key) {
        int firstHalfLength = key.length() / 2;
        String localFilename = String.valueOf(key.substring(0, firstHalfLength).hashCode());
        localFilename = localFilename + String.valueOf(key.substring(firstHalfLength).hashCode());
        return localFilename;
    }

    public File getFileForKey(String key) {
        return new File(this.mRootDirectory, this.getFilenameForKey(key));
    }

    private void pruneIfNeeded(int neededSpace) {
        if(this.mTotalSize + (long)neededSpace >= (long)this.mMaxCacheSizeInBytes) {
            if(VolleyLog.DEBUG) {
                VolleyLog.v("Pruning old cache entries.", new Object[0]);
            }

            long before = this.mTotalSize;
            int prunedFiles = 0;
            long startTime = SystemClock.elapsedRealtime();
            Iterator iterator = this.mEntries.entrySet().iterator();

            while(iterator.hasNext()) {
                java.util.Map.Entry entry = (java.util.Map.Entry)iterator.next();
                DiskBasedCache.CacheHeader e = (DiskBasedCache.CacheHeader)entry.getValue();
                boolean deleted = this.getFileForKey(e.key).delete();
                if(deleted) {
                    this.mTotalSize -= e.size;
                } else {
                    VolleyLog.d("Could not delete cache entry for key=%s, filename=%s", new Object[]{e.key, this.getFilenameForKey(e.key)});
                }

                iterator.remove();
                ++prunedFiles;
                if((float)(this.mTotalSize + (long)neededSpace) < (float)this.mMaxCacheSizeInBytes * 0.9F) {
                    break;
                }
            }

            if(VolleyLog.DEBUG) {
                VolleyLog.v("pruned %d files, %d bytes, %d ms", new Object[]{Integer.valueOf(prunedFiles), Long.valueOf(this.mTotalSize - before), Long.valueOf(SystemClock.elapsedRealtime() - startTime)});
            }

        }
    }

    private void putEntry(String key, DiskBasedCache.CacheHeader entry) {
        if(!this.mEntries.containsKey(key)) {
            this.mTotalSize += entry.size;
        } else {
            DiskBasedCache.CacheHeader oldEntry = (DiskBasedCache.CacheHeader)this.mEntries.get(key);
            this.mTotalSize += entry.size - oldEntry.size;
        }

        this.mEntries.put(key, entry);
    }

    private void removeEntry(String key) {
        DiskBasedCache.CacheHeader entry = (DiskBasedCache.CacheHeader)this.mEntries.get(key);
        if(entry != null) {
            this.mTotalSize -= entry.size;
            this.mEntries.remove(key);
        }

    }

    private static byte[] streamToBytes(InputStream in, int length) throws IOException {
        byte[] bytes = new byte[length];

        int count;
        int pos;
        for(pos = 0; pos < length && (count = in.read(bytes, pos, length - pos)) != -1; pos += count) {
            ;
        }

        if(pos != length) {
            throw new IOException("Expected " + length + " bytes, read " + pos + " bytes");
        } else {
            return bytes;
        }
    }

    private static class CacheHeader {
        public long size;
        public String key;
        public String etag;
        public long serverDate;
        public long ttl;
        public long softTtl;
        public Map<String, String> responseHeaders;

        private CacheHeader() {
        }

        public CacheHeader(String key, Entry entry) {
            this.key = key;
            this.size = (long)entry.data.length;
            this.etag = entry.etag;
            this.serverDate = entry.serverDate;
            this.ttl = entry.ttl;
            this.softTtl = entry.softTtl;
            this.responseHeaders = entry.responseHeaders;
        }

        public static DiskBasedCache.CacheHeader readHeader(InputStream is) throws IOException {
            DiskBasedCache.CacheHeader entry = new DiskBasedCache.CacheHeader();
            ObjectInputStream ois = new ObjectInputStream(is);
            byte version = ois.readByte();
            if(version != 2) {
                throw new IOException();
            } else {
                entry.key = ois.readUTF();
                entry.etag = ois.readUTF();
                if(entry.etag.equals("")) {
                    entry.etag = null;
                }

                entry.serverDate = ois.readLong();
                entry.ttl = ois.readLong();
                entry.softTtl = ois.readLong();
                entry.responseHeaders = readStringStringMap(ois);
                return entry;
            }
        }

        public Entry toCacheEntry(byte[] data) {
            Entry e = new Entry();
            e.data = data;
            e.etag = this.etag;
            e.serverDate = this.serverDate;
            e.ttl = this.ttl;
            e.softTtl = this.softTtl;
            e.responseHeaders = this.responseHeaders;
            return e;
        }

        public boolean writeHeader(OutputStream os) {
            try {
                ObjectOutputStream e = new ObjectOutputStream(os);
                e.writeByte(2);
                e.writeUTF(this.key);
                e.writeUTF(this.etag == null?"":this.etag);
                e.writeLong(this.serverDate);
                e.writeLong(this.ttl);
                e.writeLong(this.softTtl);
                writeStringStringMap(this.responseHeaders, e);
                e.flush();
                return true;
            } catch (IOException var3) {
                VolleyLog.d("%s", new Object[]{var3.toString()});
                return false;
            }
        }

        private static void writeStringStringMap(Map<String, String> map, ObjectOutputStream oos) throws IOException {
            if(map != null) {
                oos.writeInt(map.size());
                Iterator var3 = map.entrySet().iterator();

                while(var3.hasNext()) {
                    java.util.Map.Entry entry = (java.util.Map.Entry)var3.next();
                    oos.writeUTF((String)entry.getKey());
                    oos.writeUTF((String)entry.getValue());
                }
            } else {
                oos.writeInt(0);
            }

        }

        private static Map<String, String> readStringStringMap(ObjectInputStream ois) throws IOException {
            int size = ois.readInt();
            Object result = size == 0?Collections.emptyMap():new HashMap(size);

            for(int i = 0; i < size; ++i) {
                String key = ois.readUTF().intern();
                String value = ois.readUTF().intern();
                ((Map)result).put(key, value);
            }

            return (Map)result;
        }
    }

    private static class CountingInputStream extends FilterInputStream {
        private int bytesRead;

        private CountingInputStream(InputStream in) {
            super(in);
            this.bytesRead = 0;
        }

        public int read() throws IOException {
            int result = super.read();
            if(result != -1) {
                ++this.bytesRead;
            }

            return result;
        }

        public int read(byte[] buffer, int offset, int count) throws IOException {
            int result = super.read(buffer, offset, count);
            if(result != -1) {
                this.bytesRead += result;
            }

            return result;
        }
    }
}
可以看到。在这个类里,写了各种存储和读取数据的方法,找到这里找到了方向,原来图片的读取和写入在一开始的时候就已经进行了。

5.找到了这个,但是是封装的,那么怎么去清理这个缓存呢,在new队列以后,我发现,使用队列对象,可以直接获取缓存的获取和删除

mRequestQueue.getCache().get(url)  //获取单个缓存
mRequestQueue.getCache().remove(url);  //清除单个缓存
mRequestQueue.getCache().clear();     //清除全部缓存
mRequestQueue.getCache().put(url,bitmap);  //放入缓存

 再加上清理内存缓存的方法

cache.remove(getCacheKey(url, maxWidth, maxHeight));
//同ImageLoader里私有方法
private static String getCacheKey(String url, int maxWidth, int maxHeight) {
    return (new StringBuilder(url.length() + 12)).append("#W").append(maxWidth).append("#H").append(maxHeight).append(url).toString();
}
cache.evictAll();

这样,volley的所有缓存都得到了清理



但是在什么时候存的,怎么取得,我研究了这个文章,但是还是不够通透,http://blog.csdn.net/asdzheng/article/details/45955653       这个更详细http://www.w2bc.com/Article/20215   想要深入了解可以进去研究下,都是分析源码的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值