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