LruCache使用方法

LruCache 的文档描述
A cache that holds strong references to a limited number of values. Each time a value is accessed, it is moved to the head of a queue. When a value is added to a full cache, 
the value at the end of that queue is evicted and may become eligible for garbage collection.
1 一个包含有限数量强引用的缓存,一定数量的map。
2 每次访问一个值,它都会被移动到队列的头部,
3 将一个新的值添加到已经满了的缓存队列时,该队列末尾的值将会被逐出,并且可能会被垃圾回收机制进行回收。
LruCache 构造函数
创建了一个 LinkedHashMap,三个参数分别为 初始容量、加载因子和访问顺序,当 accessOrder 为 true 时,这个集合的元素顺序就会是访问顺序,也就是访问了之后就会将这个元素放到集合的最后面。

public LruCache(int maxSize) {
    if (maxSize <= 0) {
        throw new IllegalArgumentException("maxSize <= 0");
    }
    this.maxSize = maxSize;
    this.map = new LinkedHashMap<K, V>(0, 0.75f, true);
}
        int cacheSize = 1024 * 1024 * memClass;
        int mCacheSize = maxMemory / 8;//设置图片内存缓存占用八分之一
        mMemoryCache = new LruCache<String, BitmapItem>(cacheSize) {
            @Override //必须重写此方法,来测量Bitmap的大小
            protected int sizeOf(String key, BitmapItem bitmap) {
                return bitmap.mBitmap.getByteCount();
            }
        };
     public void getBitmap(BitmapWorkerOptions options, final BitmapCallback callback) {
        cancelDownload(callback);
        final boolean hasAccountImageUri = UriUtils.isAccountImageUri(options.getResourceUri());
        final Bitmap bitmap = hasAccountImageUri ? null : getBitmapFromMemCache(options);
        if (hasAccountImageUri) {
            AccountImageChangeObserver.getInstance().registerChangeUriIfPresent(options);
        }

        BitmapWorkerTask task = new BitmapWorkerTask(null) {
            @Override
            protected Bitmap doInBackground(BitmapWorkerOptions... params) {
                if (bitmap != null) {
                    return bitmap;
                }
                final Bitmap bitmap = super.doInBackground(params);
                if (bitmap != null && !hasAccountImageUri) {
                    addBitmapToMemoryCache(params[0], bitmap, isScaled());
                }
                return bitmap;
            }

            @Override
            protected void onPostExecute(Bitmap bitmap) {
                callback.onBitmapRetrieved(bitmap);//获取图片回调。
            }
        };
        callback.mTask = new SoftReference<>(task); 生成下载线程的弱引用
        task.executeOnExecutor(BITMAP_DOWNLOADER_THREAD_POOL_EXECUTOR, options); 把线程放到线程池执行。
    }
    
    //发起任务下载完bitmap:加入LruCache
    private void addBitmapToMemoryCache(BitmapWorkerOptions key, Bitmap bitmap, boolean isScaled) {
        if (!key.isMemCacheEnabled()) {
            return;
        }
        String bucketKey = getBucketKey(
                key.getCacheKey(), key.getBitmapConfig(), bitmap.getHeight());
        BitmapItem bitmapItem = mMemoryCache.get(bucketKey);
        if (bitmapItem != null) {
            Bitmap currentBitmap = bitmapItem.mBitmap;
            // If somebody else happened to get a larger one in the bucket, discard our bitmap.
            // TODO: need a better way to prevent current downloading for the same Bitmap
            if (currentBitmap.getWidth() >= bitmap.getWidth() && currentBitmap.getHeight()
                    >= bitmap.getHeight()) {
                return;
            }
        }
        if (DEBUG) {
            Log.d(TAG, "add cache "+bucketKey+" isScaled = "+isScaled);
        }
        bitmapItem = new BitmapItem(bitmap, isScaled);
        mMemoryCache.put(bucketKey, bitmapItem);加到缓存
    }
    private Bitmap getBitmapFromMemCache(BitmapWorkerOptions key) {
        if (key.getHeight() != BitmapWorkerOptions.MAX_IMAGE_DIMENSION_PX) {
            // 1. find the bitmap in the size bucket
            String bucketKey =
                    getBucketKey(key.getCacheKey(), key.getBitmapConfig(), key.getHeight());
            BitmapItem bitmapItem = mMemoryCache.get(bucketKey);获取
            if (bitmapItem != null) {
                Bitmap bitmap = bitmapItem.mBitmap;
                // now we have the bitmap in the bucket, use it when the bitmap is not scaled or
                // if the size is larger than or equals to the output size
                if (!bitmapItem.mScaled) {
                    return bitmap;
                }
                if (bitmap.getHeight() >= key.getHeight()) {
                    return bitmap;
                }
            }
            // 2. find un-scaled bitmap in smaller buckets.  If the un-scaled bitmap exists
            // in higher buckets,  we still need to scale it down.  Right now we just
            // return null and let the BitmapWorkerTask to do the same job again.
            // TODO: use the existing unscaled bitmap and we don't need to load it from resource
            // or network again.
            for (int i = SIZE_BUCKET.length - 1; i >= 0; i--) {
                if (SIZE_BUCKET[i] >= key.getHeight()) {
                    continue;
                }
                bucketKey = getBucketKey(key.getCacheKey(), key.getBitmapConfig(), SIZE_BUCKET[i]);
                bitmapItem = mMemoryCache.get(bucketKey);
                if (bitmapItem != null && !bitmapItem.mScaled) {
                    return bitmapItem.mBitmap;
                }
            }
            return null;
        }
        // 3. find un-scaled bitmap if size is not specified
        for (int i = SIZE_BUCKET.length - 1; i >= 0; i--) {
            String bucketKey =
                    getBucketKey(key.getCacheKey(), key.getBitmapConfig(), SIZE_BUCKET[i]);
            BitmapItem bitmapItem = mMemoryCache.get(bucketKey);
            if (bitmapItem != null && !bitmapItem.mScaled) {
                return bitmapItem.mBitmap;
            }
        }
        return null;
    }    
            applicationContext.registerComponentCallbacks(new ComponentCallbacks2() {
            @Override
            public void onTrimMemory(int level) {
                mMemoryCache.evictAll(); 内存不足 清理内存缓存。
            }

            @Override
            public void onConfigurationChanged(Configuration newConfig) {
                int changes = mConfiguration.updateFrom(newConfig);
                if (Configuration.needNewResources(changes, ActivityInfo.CONFIG_LAYOUT_DIRECTION)) {
                    invalidateCachedResources(); 旋转屏幕时清理指定缓存
                }
            }

            @Override
            public void onLowMemory() {}
        });
            public void invalidateCachedResources() {
        Map<String, BitmapItem> snapshot = mMemoryCache.snapshot();
        for (String uri: snapshot.keySet()) {
            Log.d(TAG, "remove cached image: " + uri);
            if (uri.startsWith(ContentResolver.SCHEME_ANDROID_RESOURCE)) {
                mMemoryCache.remove(uri);从缓存中清理。
            }
        }
    }
重要的部分:如何调用:
    Uri iconUri = getIconResourceUri();
        if (iconUri != null) {
                    iconImageView.setVisibility(View.INVISIBLE);
                    if (mActivity != null) {
                        BitmapDownloader bitmapDownloader = BitmapDownloader.getInstance(mActivity);
                        mBitmapCallBack = new BitmapCallback() {
                            @Override
                            public void onBitmapRetrieved(Bitmap bitmap) {//回调
                                if (bitmap != null) {
                                    mIconBitmap = bitmap;
                                    iconImageView.setVisibility(View.VISIBLE);
                                    iconImageView.setImageBitmap(bitmap);
                                    addShadow(iconImageView, view);
                                    updateViewSize(iconImageView);
                                }
                            }
                        };

                        bitmapDownloader.getBitmap(new BitmapWorkerOptions.Builder(
                                mActivity).resource(iconUri)
                                .width(iconImageView.getLayoutParams().width).build(),
                                mBitmapCallBack);
                    }
    public static abstract class BitmapCallback {
        SoftReference<BitmapWorkerTask> mTask;

        public abstract void onBitmapRetrieved(Bitmap bitmap);
    }
    getBitmap中
    callback.mTask = new SoftReference<>(task);生成下载线程的弱引用
        task.executeOnExecutor(BITMAP_DOWNLOADER_THREAD_POOL_EXECUTOR, options);
        
    imageView.setTag(R.id.imageDownloadTask, new SoftReference<>(task));
    
        public boolean cancelDownload(Object key) {
        BitmapWorkerTask task = null;
        if (key instanceof ImageView) {
            ImageView imageView = (ImageView)key;
            SoftReference<BitmapWorkerTask> softReference =
                    (SoftReference<BitmapWorkerTask>) imageView.getTag(R.id.imageDownloadTask);
            if (softReference != null) {
                task = softReference.get();
                softReference.clear();
            }
        } else if (key instanceof BitmapCallback) {
            BitmapCallback callback = (BitmapCallback)key;
            if (callback.mTask != null) {
                task = callback.mTask.get();
                callback.mTask = null;
            }
        }
        if (task != null) {
            return task.cancel(true);
        }
        return false;
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值