volley 缓存清理不干净

来源:互联网 发布:windows安装jdk 编辑:程序博客网 时间:2024/05/01 23:38

公司做的框架使用的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   想要深入了解可以进去研究下,都是分析源码的

0 0
原创粉丝点击