如何在内存中缓存内存和光盘缓存中的位图?

时间:2013-12-09 17:25:47

标签: android caching bitmap xamarin.android universal-image-loader

从当前用户的设备相机或图库中获取或获取照片后,如何实施下一个StoreImage方法的最佳方法是什么? (使用Android Universal Image Loader

#region IImageManager

// Stores the given bitmap inside both memory and disc caches...
public override void StoreImage (object rawImage, string key, bool toDisc)
{
    // Given key examples:
    // local_photo_66831.jpg
    // local_thumbnail_photo_66831.jpg  

    string uri = MakeUri (key);

    // Returned uri examples:
    // file:///storage/sdcard0/Android/data/com.xxx.xxx/cache/local_photo_66831.jpg
    // file:///storage/sdcard0/Android/data/com.xxx.xxx/cache/local_thumbnail_photo_66831.jpg   

    ImageLoader.Instance.MemoryCache.Put (uri, (Bitmap)rawImage);

    if (toDisc)
        ImageLoader.Instance.DiscCache.Put (uri, <File>);
}

问题:

  • 如何在DiscCache内保存当前内存位图?
  • 是否可以通过编程方式将文件添加到DiscCache,而不是使用LoadImage方法加载它们?
  • 是否可以使用简单的字符串* key * s而不是始终创建本地* URI * s,然后使用类似'ImageLoader.Instance的调用来访问它们.MemoryCache.Get(key)'?

我正在尝试将下一个iOS-SDWebImage实现移植到类似的Android-UIL版本:

public override void StoreImage (object rawImage, string key, bool toDisk)
{
    SDWebImageManager.SharedManager.ImageCache.StoreImage ((UIImage)rawImage, key, toDisk);
}

提前致谢。

1 个答案:

答案 0 :(得分:1)

在imageLoader类下面,以便在下载图像后保持缓存内存和磁盘内存到磁盘中的映像存储。

public class MyImageLoader {

private static final int DISK_CACHE_SIZE = 1024 * 1024 * 10; // 10MB
private static final String DISK_CACHE_SUBDIR = "ImageCache";
private DiskLruImageCache mDiskLruImageCache;
private ExecutorService executorService;
private LruCache<String, Bitmap> mMemoryCache;
private Map<ImageView, String> imageViews = Collections.synchronizedMap(new WeakHashMap<ImageView, String>());
private int byteCounts;
private int requiredHeight = 100, requiredWidth = 100; // setting default height & width as 100
private final int default_icon = R.drawable.no_image_friend;
CommonMethod mCommonMethod;

public MyImageLoader(Context context) {

    executorService = Executors.newFixedThreadPool(2);
    final int memClass = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();
    // Use 1/8th of the available memory for this memory cache.
    final int cacheSize = 1024 * 1024 * memClass / 8;

    mCommonMethod = new CommonMethod(context);
    mDiskLruImageCache = new DiskLruImageCache(context, DISK_CACHE_SUBDIR, DISK_CACHE_SIZE, CompressFormat.PNG, 70);

    mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {

        @Override
        protected int sizeOf(String key, Bitmap bitmap) {
            byteCounts = bitmap.getRowBytes() * bitmap.getHeight();
            return byteCounts;
        }
    };
}

public void ExecuteLoading(String urlString, ImageView mImageView) {

    imageViews.put(mImageView, urlString);
    Bitmap bitmap = getBitmapFromMemCache(urlString);

    if (bitmap != null){
        mImageView.setImageBitmap(bitmap);
    }
    else {
        executorService.submit(new LoadImages(urlString, mImageView));
        mImageView.setImageResource(default_icon);
    }
}

boolean ImageViewReused(String urlString, ImageView mImageView){
    String tag=imageViews.get(mImageView);
    if(tag==null || !tag.equals(urlString))
        return true;
    return false;
}

class LoadImages implements Runnable {
    String urlString;
    ImageView mImageView;
    DisplayImages images;

    public LoadImages(String urlString, ImageView mImageView) {
        this.urlString = urlString;
        this.mImageView = mImageView;
    }

    public void run() {

        if(!ImageViewReused(urlString, mImageView)){
            Bitmap bitmap = DownloadFromUrl(urlString);

            Bitmap mBitmapMask = mCommonMethod.makeMaskImageCrop(bitmap, R.drawable.image_thumb_mask, R.drawable.image_thumb);

            //TODO to mask image then bitmap pass
            addBitmapToDiskCache(urlString, mBitmapMask);

            DisplayImages images = new DisplayImages(urlString, mImageView, mBitmapMask);
            ((Activity) mImageView.getContext()).runOnUiThread(images);
        }
    }
}

class DisplayImages implements Runnable {
    Bitmap bitmap;
    String urlString;
    ImageView mImageView;

    public DisplayImages(String urlString, ImageView mImageView, Bitmap bitmap) {
        this.urlString = urlString;
        this.mImageView = mImageView;
        this.bitmap = bitmap;
    }

    public void run() {

        if(!ImageViewReused(urlString, mImageView)){
            if (bitmap != null)
                mImageView.setImageBitmap(bitmap);
            else
                mImageView.setImageResource(default_icon);
        }
    }
}

private Bitmap DownloadFromUrl(String urlString) {
    return decodeBitmapFromStream(urlString, getReqiredWidth(), getRequiredHeight());
}

private void addBitmapToMemoryCache(String key, Bitmap bitmap) {
    synchronized (mMemoryCache) {
        if (mMemoryCache.get(key) == null) {
            mMemoryCache.put(key, bitmap);
        }
    }
}
private Bitmap getBitmapFromMemCache(String key) {
    Bitmap bitmap = mMemoryCache.get(key);
    if(bitmap == null){
        bitmap = getBitmapFromDiskCache(key);
    }
    return bitmap;
}

private void addBitmapToDiskCache(String key, Bitmap bitmap) {
    synchronized (mDiskLruImageCache) {
        if (!mDiskLruImageCache.containsKey(String.valueOf(key.hashCode()))) {
            mDiskLruImageCache.put(String.valueOf(key.hashCode()), bitmap);
            addBitmapToMemoryCache(key, bitmap);
        }
    }
}

private Bitmap getBitmapFromDiskCache(String key) {
    return mDiskLruImageCache.getBitmap(String.valueOf(key.hashCode()));
}


private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    inSampleSize = Math.min(width/reqWidth, height/reqHeight);

    return inSampleSize;
}

private static Bitmap decodeBitmapFromStream(String urlString, int reqWidth, int reqHeight) {

    URL url = null;
    InputStream is = null;
    try {
        url = new URL(urlString);
        is = (InputStream) url.getContent();
    } catch (Exception e) {
        e.printStackTrace();
    }

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(is, null, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // As InputStream can be used only once we have to regenerate it again.
    try {
        is = (InputStream) url.getContent();
    } catch (IOException e) {
        e.printStackTrace();
    }
    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return  BitmapFactory.decodeStream(is, null, options);
}

public int getRequiredHeight() {
    return requiredHeight;
}

public void setRequiredHeight(int longest, int requiredHeight) {
    this.requiredHeight = requiredHeight > longest ? longest : requiredHeight;
}

public int getReqiredWidth() {
    return requiredWidth;
}

public void setReqiredWidth(int longest, int requiredWidth) {
    this.requiredWidth = requiredWidth > longest ? longest : requiredWidth; 
}

public void clearCacheMemory() {
    if(mMemoryCache.size() > 0){
        mMemoryCache.evictAll();
    }
}

public void clearDiskMemory() {
    mDiskLruImageCache.clearCache();
}
}

希望你能从上面的代码中得到一些想法和提示..