Android Universal Image Loader 디스크 캐시 분석

13299 단어
전언
그림 로드에 있어서 UIL은 정말 유용하다. 틈나는 대로 UIL의 원본을 보면 스스로 원리를 이해하고 더욱 능숙하게 사용할 수 있다.
소스 버전: Android-Universal-Image-Loader-1.9.5
프로젝트 주소: Universal-Image-Loader
참고: 이 버전의 discache는 유효하지 않습니다. diskCache로 바꿉니다.
디스크 캐시 분석
DisplayImageOptions 디스크 캐시 설정
options.cacheOnDisk(true);

ImageLoaderConfiguration에서 디스크 캐시 공간 구성
config.diskCacheSize(50 * 1024 * 1024); // 50 MiB
config.diskCache(new UnlimitedDiskCache(cacheDir)); //             
  • 1.디스크 캐시 경로
  • 사용자 정의 캐시 경로를 사용한다면 물론 문제없지만, 기본 캐시 경로를 알아야 한다고 생각합니다. 그렇지 않으면 캐시가 성공했는지 어떻게 알 수 있을까요?
    캐시 디렉토리 가져오기
    File file = ImageLoader.getInstance().getDiskCache().getDirectory();
    String filePath = file.getAbsolutePath();

    결과는 다음과 같습니다./storage/emulated/0/Android/data/com.nostra13.universalimageloader/cache/uil-images 즉:SD카드에 있는 안드로이드/data/응용 프로그램 패키지 이름/cache/uil-images 폴더 아래:/Android/data/com.baidu.netdisk/cache/uil-images
    이 폴더 아래의 파일을 복사해서 접미사 이름을 붙여라.jpg에서 그림을 볼 수 있습니다.
    DiskCache의 원본 섹션DefaultConfigurationFactory를 만듭니다.java
        /**
         * Creates default implementation of {@link DiskCache} depends on incoming parameters
         */
        public static DiskCache createDiskCache(Context context,
                FileNameGenerator diskCacheFileNameGenerator,
                long diskCacheSize, int diskCacheFileCount) {
            File reserveCacheDir = createReserveDiskCacheDir(context);
            if (diskCacheSize > 0 || diskCacheFileCount > 0) {
                File individualCacheDir = StorageUtils.getIndividualCacheDirectory(context);
                try {
                    return new LruDiskCache(individualCacheDir, reserveCacheDir, 
                    diskCacheFileNameGenerator, diskCacheSize,diskCacheFileCount);
                    //LruDiskCache                  。
                } catch (IOException e) {
                    L.e(e);
                    // continue and create unlimited cache
                }
            }
            File cacheDir = StorageUtils.getCacheDirectory(context);
            return new UnlimitedDiskCache(cacheDir, reserveCacheDir, diskCacheFileNameGenerator);
        }
    
        /** Creates reserve disk cache folder which will be used if primary disk cache folder becomes unavailable */
        private static File createReserveDiskCacheDir(Context context) {
            File cacheDir = StorageUtils.getCacheDirectory(context, false);
            File individualDir = new File(cacheDir, "uil-images");//      
            if (individualDir.exists() || individualDir.mkdir()) {
                cacheDir = individualDir;
            }
            return cacheDir;
        }
  • 2.디스크 캐시 타이밍
  • 디스크 캐시가 켜져 있으면: cacheOndisk =true;
    DisplayImageOptions에서자바, 누가 호출했는지 보자.
        public boolean isCacheOnDisk() {
            return cacheOnDisk;
        }

    의심할 여지없이 그림을 불러오기 전에 LoadAndDisplayImageTask를 사용해야 합니다.java
        private Bitmap tryLoadBitmap() throws TaskCancelledException {
            Bitmap bitmap = null;
            try {
                File imageFile = configuration.diskCache.get(uri);
                if (imageFile != null && imageFile.exists() && imageFile.length() > 0) {
                //            ~
                    L.d(LOG_LOAD_IMAGE_FROM_DISK_CACHE, memoryCacheKey);
                    loadedFrom = LoadedFrom.DISC_CACHE;
    
                    checkTaskNotActual();
                    bitmap = decodeImage(Scheme.FILE.wrap(imageFile.getAbsolutePath()));
                }
                if (bitmap == null || bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0) {
                    L.d(LOG_LOAD_IMAGE_FROM_NETWORK, memoryCacheKey);
                    loadedFrom = LoadedFrom.NETWORK;
    
                    String imageUriForDecoding = uri;
                    if (options.isCacheOnDisk() && tryCacheImageOnDisk()) {
                    //          ,     tryCacheImageOnDisk()
                        imageFile = configuration.diskCache.get(uri);
                        if (imageFile != null) {
                            imageUriForDecoding = Scheme.FILE.wrap(imageFile.getAbsolutePath());
                        }
                    }
    
                    checkTaskNotActual();
                    bitmap = decodeImage(imageUriForDecoding);
                    //  imageUriForDecoding    uri      ,      
                    //decodeImage      ImageDownloader.getStream()  
    
                    if (bitmap == null || bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0) {
                        fireFailEvent(FailType.DECODING_ERROR, null);
                    }
                }
            } catch (IllegalStateException e) {
                fireFailEvent(FailType.NETWORK_DENIED, null);
            } catch (TaskCancelledException e) {
                throw e;
            } catch (IOException e) {
                L.e(e);
                fireFailEvent(FailType.IO_ERROR, e);
            } catch (OutOfMemoryError e) {
                L.e(e);
                fireFailEvent(FailType.OUT_OF_MEMORY, e);
            } catch (Throwable e) {
                L.e(e);
                fireFailEvent(FailType.UNKNOWN, e);
            }
            return bitmap;
        }

    tryCacheImageOnDisk () 방법
        /** @return true - if image was downloaded successfully; false - otherwise */
        private boolean tryCacheImageOnDisk() throws TaskCancelledException {
            L.d(LOG_CACHE_IMAGE_ON_DISK, memoryCacheKey);
    
            boolean loaded;
            try {
                loaded = downloadImage();//     
                if (loaded) {
                //    
                    int width = configuration.maxImageWidthForDiskCache;
                    int height = configuration.maxImageHeightForDiskCache;
                    if (width > 0 || height > 0) {
                        L.d(LOG_RESIZE_CACHED_IMAGE_FILE, memoryCacheKey);
                        resizeAndSaveImage(width, height); // TODO : process boolean result
                        //             
                    }
                }
            } catch (IOException e) {
                L.e(e);
                loaded = false;
            }
            return loaded;
        }

    그림 다운로드 방법:downloadImage()
        private boolean downloadImage() throws IOException {
            InputStream is = getDownloader().getStream(uri, options.getExtraForDownloader());
            if (is == null) {
                L.e(ERROR_NO_IMAGE_STREAM, memoryCacheKey);
                return false;
            } else {
                try {
                    return configuration.diskCache.save(uri, is, this);
                    //    ,  diskCache
                } finally {
                    IoUtils.closeSilently(is);
                }
            }
        }

    그림 사용자 구성에 따라 resizeAndSaveImage 다시 저장(int maxWidth, int maxHeight)
        /** Decodes image file into Bitmap, resize it and save it back */
        private boolean resizeAndSaveImage(int maxWidth, int maxHeight) throws IOException {
            // Decode image file, compress and re-save it
            boolean saved = false;
            File targetFile = configuration.diskCache.get(uri);
            //            ?     ~
            if (targetFile != null && targetFile.exists()) {
                ImageSize targetImageSize = new ImageSize(maxWidth, maxHeight);
                DisplayImageOptions specialOptions = new DisplayImageOptions.Builder().cloneFrom(options)
                        .imageScaleType(ImageScaleType.IN_SAMPLE_INT).build();
                ImageDecodingInfo decodingInfo = new ImageDecodingInfo(memoryCacheKey,
                        Scheme.FILE.wrap(targetFile.getAbsolutePath()), uri, targetImageSize, ViewScaleType.FIT_INSIDE,
                        getDownloader(), specialOptions);
                Bitmap bmp = decoder.decode(decodingInfo);
                if (bmp != null && configuration.processorForDiskCache != null) {
                    L.d(LOG_PROCESS_IMAGE_BEFORE_CACHE_ON_DISK, memoryCacheKey);
                    bmp = configuration.processorForDiskCache.process(bmp);
                    if (bmp == null) {
                        L.e(ERROR_PROCESSOR_FOR_DISK_CACHE_NULL, memoryCacheKey);
                    }
                }
                if (bmp != null) {
                    saved = configuration.diskCache.save(uri, bmp);
                    //ok       
                    bmp.recycle();
                }
            }
            return saved;
        }
  • 3 디스크 캐시 유형
  • Limited Age Disk Cache와 Unlimited Disk Cache 둘 다 Base Disk Cache를 계승했습니다.
  • LimitedageDiskCache는 캐시 대상의 가장 긴 생존 주기 디스크 캐시를 제한한다.
  • Unlimited Disk Cache와 Base Disk Cache는 별 차이가 없다. 단지 이름이 더 이해가 간다.
  •     DiskCache diskCache;
        if (limit > 0) {//limit  Max file age (in seconds)
            diskCache = new LimitedAgeDiskCache(cacheDir, limit);
        } else {
            diskCache = new UnlimitedDiskCache(cacheDir);
        }
        config.diskCache(diskCache);

    좋은 웹페이지 즐겨찾기