/** Trims the cache according to the specified trimming strategy and the given trim type. */ @Override public void trim(MemoryTrimType trimType) { ArrayList<Entry<K, V>> oldEntries; final double trimRatio = mCacheTrimStrategy.getTrimRatio(trimType); synchronized (this) { int targetCacheSize = (int) (mCachedEntries.getSizeInBytes() * (1 - trimRatio)); int targetEvictionQueueSize = Math.max(0, targetCacheSize - getInUseSizeInBytes()); oldEntries = trimExclusivelyOwnedEntries(Integer.MAX_VALUE, targetEvictionQueueSize); makeOrphans(oldEntries); } maybeClose(oldEntries); maybeNotifyExclusiveEntryRemoval(oldEntries); maybeUpdateCacheParams(); maybeEvictEntries(); }
@Override public double getTrimRatio(MemoryTrimType trimType) { switch (trimType) { case OnCloseToDalvikHeapLimit: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { return MemoryTrimType.OnCloseToDalvikHeapLimit.getSuggestedTrimRatio(); } else { // On pre-lollipop versions we keep bitmaps on the native heap, so no need to trim here // as it wouldn't help Dalvik heap anyway. return 0; } case OnAppBackgrounded: case OnSystemLowMemoryWhileAppInForeground: case OnSystemLowMemoryWhileAppInBackground: return 1; default: FLog.wtf(TAG, "unknown trim type: %s", trimType); return 0; } }
@Override public void onTrimMemory(final int level) { super.onTrimMemory(level); switch (level) { case TRIM_MEMORY_RUNNING_MODERATE: case TRIM_MEMORY_RUNNING_LOW: case TRIM_MEMORY_BACKGROUND: frescoMemoryTrimmableRegistry.trim(MemoryTrimType.OnSystemLowMemoryWhileAppInBackground); break; case TRIM_MEMORY_RUNNING_CRITICAL: case TRIM_MEMORY_COMPLETE: frescoMemoryTrimmableRegistry.trim(MemoryTrimType.OnCloseToDalvikHeapLimit); break; default: break; } }
/** * Responds to memory pressure by simply 'discarding' the local byte array if it is not used * at the moment. * * @param trimType kind of trimming to perform (ignored) */ @Override public void trim(MemoryTrimType trimType) { if (!mSemaphore.tryAcquire()) { return; } try { mByteArraySoftRef.clear(); } finally { mSemaphore.release(); } }
@Override public double getTrimRatio(MemoryTrimType trimType) { switch (trimType) { case OnCloseToDalvikHeapLimit: // Resources cached on native heap do not consume Dalvik heap, so no trimming here. return 0; case OnAppBackgrounded: case OnSystemLowMemoryWhileAppInForeground: case OnSystemLowMemoryWhileAppInBackground: return 1; default: FLog.wtf(TAG, "unknown trim type: %s", trimType); return 0; } }
@Test public void testTrim() { mArray.get(7).close(); assertEquals(8, mArray.mByteArraySoftRef.get().length); // now trim, and verify again mArray.trim(MemoryTrimType.OnCloseToDalvikHeapLimit); assertNull(mArray.mByteArraySoftRef.get()); assertEquals(1, mArray.mSemaphore.availablePermits()); }
@Test public void testTrimUnsuccessful() { CloseableReference<byte[]> arrayRef = mArray.get(7); mArray.trim(MemoryTrimType.OnCloseToDalvikHeapLimit); assertSame(arrayRef.get(), mArray.mByteArraySoftRef.get()); assertEquals(0, mArray.mSemaphore.availablePermits()); }
@Test public void testTrim() { mPool.get(7).close(); assertEquals(1, mDelegatePool.getBucket(8).getFreeListSize()); // now trim, and verify again mDelegatePool.trim(MemoryTrimType.OnCloseToDalvikHeapLimit); assertEquals(0, mDelegatePool.getBucket(8).getFreeListSize()); }
@Test public void testTrimUnsuccessful() { CloseableReference<byte[]> arrayRef = mPool.get(7); mDelegatePool.trim(MemoryTrimType.OnCloseToDalvikHeapLimit); assertNotNull(arrayRef.get()); }
public static ImagePipelineConfig getDefaultImagePipelineConfig(Context context) { final int cacheSize = (int) SharedPreferencesUtil.getData(HViewerApplication.mContext, SettingFragment.KEY_PREF_CACHE_SIZE, 300); MAX_DISK_CACHE_VERYLOW_SIZE = cacheSize / 5 * ByteConstants.MB; MAX_DISK_CACHE_LOW_SIZE = cacheSize * 3 / 5 * ByteConstants.MB; MAX_DISK_CACHE_SIZE = cacheSize * ByteConstants.MB; //内存配置 final MemoryCacheParams bitmapCacheParams = new MemoryCacheParams( MAX_MEMORY_CACHE_SIZE, // 内存缓存中总图片的最大大小,以字节为单位。 Integer.MAX_VALUE, // 内存缓存中图片的最大数量。 MAX_MEMORY_CACHE_SIZE, // 内存缓存中准备清除但尚未被删除的总图片的最大大小,以字节为单位。 Integer.MAX_VALUE, // 内存缓存中准备清除的总图片的最大数量。 Integer.MAX_VALUE); // 内存缓存中单个图片的最大大小。 //修改内存图片缓存数量,空间策略(这个方式有点恶心) Supplier<MemoryCacheParams> mSupplierMemoryCacheParams = new Supplier<MemoryCacheParams>() { @Override public MemoryCacheParams get() { return bitmapCacheParams; } }; //小图片的磁盘配置 DiskCacheConfig diskSmallCacheConfig = DiskCacheConfig.newBuilder(context) .setBaseDirectoryPath(getDiskCacheDir(context)) //缓存图片基路径 .setBaseDirectoryName(IMAGE_PIPELINE_SMALL_CACHE_DIR) //文件夹名 .setMaxCacheSize(MAX_DISK_CACHE_SIZE) //默认缓存的最大大小。 .setMaxCacheSizeOnLowDiskSpace(MAX_SMALL_DISK_LOW_CACHE_SIZE) //缓存的最大大小,使用设备时低磁盘空间。 .setMaxCacheSizeOnVeryLowDiskSpace(MAX_SMALL_DISK_VERYLOW_CACHE_SIZE) //缓存的最大大小,当设备极低磁盘空间 .setDiskTrimmableRegistry(NoOpDiskTrimmableRegistry.getInstance()) .build(); //默认图片的磁盘配置 DiskCacheConfig diskCacheConfig = DiskCacheConfig.newBuilder(context) .setBaseDirectoryPath(getDiskCacheDir(context))//缓存图片基路径 .setBaseDirectoryName(IMAGE_PIPELINE_CACHE_DIR) //文件夹名 .setMaxCacheSize(MAX_DISK_CACHE_SIZE) //默认缓存的最大大小。 .setMaxCacheSizeOnLowDiskSpace(MAX_DISK_CACHE_LOW_SIZE) //缓存的最大大小,使用设备时低磁盘空间。 .setMaxCacheSizeOnVeryLowDiskSpace(MAX_DISK_CACHE_VERYLOW_SIZE) //缓存的最大大小,当设备极低磁盘空间 .setDiskTrimmableRegistry(NoOpDiskTrimmableRegistry.getInstance()) .build(); // 自定义使用okhttp进行请求 OkHttpClient okHttpClient = new OkHttpClient.Builder() .addNetworkInterceptor(new StethoInterceptor()) .connectTimeout(30, TimeUnit.SECONDS) .readTimeout(60, TimeUnit.SECONDS) .dns(new HttpDns()) .build(); //缓存图片配置 ImagePipelineConfig.Builder configBuilder = ImagePipelineConfig.newBuilder(context) .setBitmapsConfig(Bitmap.Config.RGB_565) .setBitmapMemoryCacheParamsSupplier(mSupplierMemoryCacheParams) .setSmallImageDiskCacheConfig(diskSmallCacheConfig) .setMainDiskCacheConfig(diskCacheConfig) .setMemoryTrimmableRegistry(NoOpMemoryTrimmableRegistry.getInstance()) .setResizeAndRotateEnabledForNetwork(true) .setNetworkFetcher(new MyOkHttpNetworkFetcher(okHttpClient)); // 这段代码用于清理缓存 NoOpMemoryTrimmableRegistry.getInstance().registerMemoryTrimmable(new MemoryTrimmable() { @Override public void trim(MemoryTrimType trimType) { final double suggestedTrimRatio = trimType.getSuggestedTrimRatio(); Logger.d("ImagePipeline", String.format("onCreate suggestedTrimRatio : %d", suggestedTrimRatio)); if (MemoryTrimType.OnCloseToDalvikHeapLimit.getSuggestedTrimRatio() == suggestedTrimRatio || MemoryTrimType.OnSystemLowMemoryWhileAppInBackground.getSuggestedTrimRatio() == suggestedTrimRatio || MemoryTrimType.OnSystemLowMemoryWhileAppInForeground.getSuggestedTrimRatio() == suggestedTrimRatio ) { ImagePipelineFactory.getInstance().getImagePipeline().clearMemoryCaches(); } } }); return configBuilder.build(); }
synchronized void trim(final MemoryTrimType trimType) { for (MemoryTrimmable trimmable : trimmables) { trimmable.trim(trimType); } }
/** * Trims the pool in response to low-memory states (invoked from MemoryManager) * For now, we'll do the simplest thing, and simply clear out the entire pool. We may consider * more sophisticated approaches later. * In other words, we ignore the memoryTrimType parameter * @param memoryTrimType the kind of trimming we want to perform */ public void trim(MemoryTrimType memoryTrimType) { trimToNothing(); }
double getTrimRatio(MemoryTrimType trimType);