1

我是 SO 新手,也是 Android 编程新手!如果这个问题是微不足道的,请原谅我。

无论如何,我正在尝试创建一个画廊应用程序,它将显示文件夹中所有媒体文件(视频和图片)的缩略图。我的应用程序运行良好,除了处理图像以获取其采样位图的漫长等待时间。

我已经使用内存缓存(LruCache)解决了这个问题,但它只在用户留在应用程序中并四处导航时解决了这个问题。每次用户关闭应用程序并重新打开它时,它都会再次重新生成缓存。

在网上做了一些阅读后,我决定在内存缓存之上添加磁盘缓存,希望它能解决问题。但即使在我实施之后,问题仍然存在。不确定我是否做错了。

下面是我初始化内存缓存和磁盘缓存的代码。

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    String path = Environment.getExternalStorageDirectory().getAbsolutePath();
    if (savedInstanceState != null) {
        displayManager.cancelAsyncTask();
        path = savedInstanceState.getString(ARG_POSITION);
    }else{
        // Get memory class of this device, exceeding this amount will throw an
        // OutOfMemory exception.
        final int memClass = ((ActivityManager)getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();

        // Use 1/8th of the available memory for this memory cache.
        final int cacheSize = 1024 * 1024 * memClass / 8;

        mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
            protected int sizeOf(String key, Bitmap bitmap) {
                // The cache size will be measured in bytes rather than number of items.
                return bitmap.getByteCount();   
            }
        };
        Log.d("DEBUG_CACHE","context is "+this);
        File cacheDir = getDiskCacheDir(this, DISK_CACHE_SUBDIR);
        Log.d("DEBUG_CACHE", "cache dir is "+cacheDir.getAbsolutePath());
        new InitDiskCacheTask().execute(cacheDir);
    }

    ArrayList<File> folderList = dataManager.getFolderListWithPhotoOrVideo(path);
    ArrayList<File> thumbList = dataManager.getAllPhotosAndVideos(path);

    displayManager.setCurrentPath(path);
    displayManager.setParent(this);
    displayManager.setMemCache(mMemoryCache);
    displayManager.setFolderList(folderList);
    displayManager.setThumbnails(thumbList);
}

下面是我如何从缓存中获取缩略图(如果存在)以及如何将位图添加到缓存中。

@Override
protected Void doInBackground(Void... params) {
    int noOfThumbnails = thumbnails.size();
    for(int j=0;j<noOfThumbnails;j++){
        String filePath = thumbnails.get(j).getName();
        if(isPhoto(filePath)){
            //if file is an image file
            Uri uri = Uri.fromFile(new File(thumbnails.get(j).getAbsolutePath()));
            Bitmap thumb = getBitmapFromMemCache(filePath);
            if(thumb==null){
                thumb = getBitmapFromDiskCache(filePath);
                if(thumb==null){
                    thumb = getPreview(uri);
                    addBitmapToCache(filePath,thumb);
                }
            }
            bitmaps.add(thumb);
        }else{
            Bitmap thumb = getBitmapFromMemCache(filePath);
            if(thumb==null){
                thumb = getBitmapFromDiskCache(filePath);
                if(thumb==null){
                    thumb = ThumbnailUtils.createVideoThumbnail(thumbnails.get(j).getAbsolutePath(),MediaStore.Images.Thumbnails.MICRO_KIND);
                    addBitmapToCache(filePath,thumb);
                }
            }
            bitmaps.add(thumb);
        }
        double progress = ((double)(j+1)/(double)noOfThumbnails)*100;
        publishProgress(new Double(progress).intValue());
        if(isCancelled()){
            Log.d("DEBUG", "doInBackGround. Task cancelled");
            return null;
        }
    }
    return null;
}  

public void addBitmapToCache(String key, Bitmap bitmap) {
    if (getBitmapFromMemCache(key) == null) {
        mMemoryCache.put(key, bitmap);  
    }

    // Also add to disk cache
    synchronized (parent.mDiskCacheLock) {
        try {
            if (parent.mDiskLruCache != null && parent.mDiskLruCache.get(key) == null) {
                parent.mDiskLruCache.put(key, bitmap);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

public Bitmap getBitmapFromMemCache(String key) {
    return (Bitmap) mMemoryCache.get(key);  
}

public Bitmap getBitmapFromDiskCache( String key ) {
    Bitmap bitmap = null;
    Snapshot snapshot = null;
    try {
        snapshot = parent.mDiskLruCache.get( key );
        if ( snapshot == null ) {
            return null;
        }
        final InputStream in = snapshot.getInputStream( 0 );
        if ( in != null ) {
            final BufferedInputStream buffIn = 
            new BufferedInputStream( in, Utils.IO_BUFFER_SIZE );
            bitmap = BitmapFactory.decodeStream( buffIn );              
        }   
    } catch ( IOException e ) {
        e.printStackTrace();
    } finally {
        if ( snapshot != null ) {
            snapshot.close();
        }
    }
    return bitmap;
}

对于 DiskLruCache.java,我使用了 google 源文件(可以在这里找到)。

4

1 回答 1

0

好的!我终于明白了。(我自己的愚蠢错误.... grrr)

在此之前,我修改了 DiskLruCache.java,以便它验证任何密钥!默认情况下,它应该只使用正则表达式 [a-z0-9_-] 验证任何字符串,也就是说,不应该有任何大写字母、空格甚至换行符。我认为这没什么大不了的,所以我将其关闭并接受所有字符串。

但是错了!我将其修改回默认值,然后每次添加或获取缓存时都修改了我的密钥,完美!

谢谢!:)

于 2013-09-18T01:05:01.303 回答