@Test public void testBasicOperations() throws Exception { DefaultDiskStorage storage = getStorageSupplier(1).get(); final String resourceId1 = "R1"; final String resourceId2 = "R2"; // no file - get should fail BinaryResource resource1 = storage.getResource(resourceId1, null); Assert.assertNull(resource1); // write out the file now byte[] key1Contents = new byte[] {0, 1, 2}; writeToStorage(storage, resourceId1, key1Contents); // get should succeed now resource1 = storage.getResource(resourceId1, null); Assert.assertNotNull(resource1); File underlyingFile = ((FileBinaryResource) resource1).getFile(); Assert.assertArrayEquals(key1Contents, Files.toByteArray(underlyingFile)); // remove the file now - get should fail again Assert.assertTrue(underlyingFile.delete()); resource1 = storage.getResource(resourceId1, null); Assert.assertNull(resource1); // no file BinaryResource resource2 = storage.getResource(resourceId2, null); Assert.assertNull(resource2); }
/** * @param url 指定的url * @return 获取制定url的图片,需要保存为xx.jpg格式。 */ public File getFileFromDiskCache(String url) { File localFile = null; if (!TextUtils.isEmpty(url)) { CacheKey cacheKey = DefaultCacheKeyFactory.getInstance().getEncodedCacheKey(ImageRequest.fromUri(url), null); BinaryResource resource; if (ImagePipelineFactory.getInstance().getMainFileCache().hasKeySync(cacheKey)) { resource = ImagePipelineFactory.getInstance().getMainFileCache().getResource(cacheKey); localFile = ((FileBinaryResource) resource).getFile(); } else if (ImagePipelineFactory.getInstance().getSmallImageFileCache().hasKey(cacheKey)) { resource = ImagePipelineFactory.getInstance().getSmallImageFileCache().getResource(cacheKey); localFile = ((FileBinaryResource) resource).getFile(); } } return localFile; }
@Override protected File doInBackground(Void... params) { final String url = shot.getTeaserUrl(); try { ImageRequest imageRequest = ImageRequest.fromUri(url); CacheKey cacheKey = DefaultCacheKeyFactory.getInstance().getEncodedCacheKey(imageRequest); // ImagePipeline imagePipeline = Fresco.getImagePipeline(); // imagePipeline.prefetchToDiskCache(imageRequest,activity); BinaryResource resource = ImagePipelineFactory.getInstance().getMainDiskStorageCache().getResource(cacheKey); File file = ((FileBinaryResource) resource).getFile(); String fileName = url; fileName = fileName.substring(fileName.lastIndexOf('/') + 1); File renamed = new File(file.getParent(), fileName); if (!renamed.exists()) { FileUtil.copy(file, renamed); } return renamed; } catch (Exception ex) { Log.w("SHARE", "Sharing " + url + " failed", ex); return null; } }
@Override public void viewImageMedia(int position, boolean loaded) { if(loaded){ PostItem item = getItem(position); CacheKey cacheKey = DefaultCacheKeyFactory.getInstance() .getEncodedCacheKey(ImageRequest .fromUri(Uri.parse(item.getUrl()))); if(cacheKey != null){ BinaryResource resource = ImagePipelineFactory.getInstance().getMainDiskStorageCache().getResource(cacheKey); File localFile; if(resource != null){ localFile = ((FileBinaryResource) resource).getFile(); Bundle bundle = new Bundle(); bundle.putString(getResources().getString(R.string.local_cache_key), localFile.getPath()); bundle.putString(getResources().getString(R.string.main_data_key), gson.toJson(item)); ((SlidingUpPanelActivity)context).setPanelView(Fragments.IMAGE_PREVIEW, bundle); } } } }
private void displayCachedImageFromBackgroundThread(ImageRequest request){ CacheKey cacheKey = DefaultCacheKeyFactory.getInstance().getEncodedCacheKey(ImageRequest.fromUri(request.getSourceUri())); if(cacheKey != null){ BinaryResource resource = ImagePipelineFactory.getInstance().getMainDiskStorageCache().getResource(cacheKey); if(resource != null){ File localFile = ((FileBinaryResource) resource).getFile(); if(localFile != null){ Handler handler = new Handler(Looper.getMainLooper()); handler.post(new Runnable() { @Override public void run() { imagePreview.setImage(ImageSource.uri(localFile.getPath())); } }); } } } }
/** * Retrieves the file corresponding to the mKey, if it is in the cache. Also * touches the item, thus changing its LRU timestamp. If the file is not * present in the file cache, returns null. * <p> * This should NOT be called on the UI thread. * * @param key the mKey to check * @return The resource if present in cache, otherwise null */ @Override public BinaryResource getResource(final CacheKey key) { String resourceId = null; SettableCacheEvent cacheEvent = SettableCacheEvent.obtain() .setCacheKey(key); try { synchronized (mLock) { BinaryResource resource = null; List<String> resourceIds = CacheKeyUtil.getResourceIds(key); for (int i = 0; i < resourceIds.size(); i++) { resourceId = resourceIds.get(i); cacheEvent.setResourceId(resourceId); resource = mStorage.getResource(resourceId, key); if (resource != null) { break; } } if (resource == null) { mCacheEventListener.onMiss(cacheEvent); mResourceIndex.remove(resourceId); } else { mCacheEventListener.onHit(cacheEvent); mResourceIndex.add(resourceId); } return resource; } } catch (IOException ioe) { mCacheErrorLogger.logError( CacheErrorLogger.CacheErrorCategory.GENERIC_IO, TAG, "getResource", ioe); cacheEvent.setException(ioe); mCacheEventListener.onReadException(cacheEvent); return null; } finally { cacheEvent.recycle(); } }
/** * Commits the provided temp file to the cache, renaming it to match * the cache's hashing convention. */ private BinaryResource endInsert( final DiskStorage.Inserter inserter, final CacheKey key, String resourceId) throws IOException { synchronized (mLock) { BinaryResource resource = inserter.commit(key); mResourceIndex.add(resourceId); mCacheStats.increment(resource.size(), 1); return resource; } }
@Override public BinaryResource insert(CacheKey key, WriterCallback callback) throws IOException { // Write to a temp file, then move it into place. This allows more parallelism // when writing files. SettableCacheEvent cacheEvent = SettableCacheEvent.obtain() .setCacheKey(key); mCacheEventListener.onWriteAttempt(cacheEvent); String resourceId; synchronized (mLock) { // for multiple resource ids associated with the same image, we only write one file resourceId = CacheKeyUtil.getFirstResourceId(key); } cacheEvent.setResourceId(resourceId); try { // getting the file is synchronized DiskStorage.Inserter inserter = startInsert(resourceId, key); try { inserter.writeData(callback, key); // Committing the file is synchronized BinaryResource resource = endInsert(inserter, key, resourceId); cacheEvent.setItemSize(resource.size()) .setCacheSize(mCacheStats.getSize()); mCacheEventListener.onWriteSuccess(cacheEvent); return resource; } finally { if (!inserter.cleanUp()) { FLog.e(TAG, "Failed to delete temp file"); } } } catch (IOException ioe) { cacheEvent.setException(ioe); mCacheEventListener.onWriteException(cacheEvent); FLog.e(TAG, "Failed inserting a file into the cache", ioe); throw ioe; } finally { cacheEvent.recycle(); } }
@Override public BinaryResource getResource(String resourceId, Object debugInfo) { final File file = getContentFileFor(resourceId); if (file.exists()) { file.setLastModified(mClock.now()); return FileBinaryResource.createOrNull(file); } return null; }
@Override public BinaryResource commit(Object debugInfo) throws IOException { // the temp resource must be ours! File targetFile = getContentFileFor(mResourceId); try { FileUtils.rename(mTemporaryFile, targetFile); } catch (FileUtils.RenameException re) { CacheErrorLogger.CacheErrorCategory category; Throwable cause = re.getCause(); if (cause == null) { category = CacheErrorLogger.CacheErrorCategory.WRITE_RENAME_FILE_OTHER; } else if (cause instanceof FileUtils.ParentDirNotFoundException) { category = CacheErrorLogger.CacheErrorCategory.WRITE_RENAME_FILE_TEMPFILE_PARENT_NOT_FOUND; } else if (cause instanceof FileNotFoundException) { category = CacheErrorLogger.CacheErrorCategory.WRITE_RENAME_FILE_TEMPFILE_NOT_FOUND; } else { category = CacheErrorLogger.CacheErrorCategory.WRITE_RENAME_FILE_OTHER; } mCacheErrorLogger.logError( category, TAG, "commit", re); throw re; } if (targetFile.exists()) { targetFile.setLastModified(mClock.now()); } return FileBinaryResource.createOrNull(targetFile); }
@Test public void testEntryIds() throws Exception { DefaultDiskStorage storage = getStorageSupplier(1).get(); final byte[] value1 = new byte[101]; final byte[] value2 = new byte[102]; final byte[] value3 = new byte[103]; value1[80] = 123; value2[80] = 45; value3[80] = 67; writeFileToStorage(storage, "resourceId1", value1); writeFileToStorage(storage, "resourceId2", value2); writeFileToStorage(storage, "resourceId3", value3); // check that resources are retrieved by the right name, before testing getEntries BinaryResource res1 = storage.getResource("resourceId1", null); BinaryResource res2 = storage.getResource("resourceId2", null); BinaryResource res3 = storage.getResource("resourceId3", null); assertArrayEquals(value1, res1.read()); assertArrayEquals(value2, res2.read()); assertArrayEquals(value3, res3.read()); // obtain entries and sort by name List<DiskStorage.Entry> entries = new ArrayList<>(storage.getEntries()); Collections.sort(entries, new Comparator<DiskStorage.Entry>() { @Override public int compare(DiskStorage.Entry lhs, DiskStorage.Entry rhs) { return lhs.getId().compareTo(rhs.getId()); } }); assertEquals(3, entries.size()); assertEquals("resourceId1", entries.get(0).getId()); assertEquals("resourceId2", entries.get(1).getId()); assertEquals("resourceId3", entries.get(2).getId()); assertArrayEquals(value1, entries.get(0).getResource().read()); assertArrayEquals(value2, entries.get(1).getResource().read()); assertArrayEquals(value3, entries.get(2).getResource().read()); }
@Test public void testCacheEventListener() throws Exception { // 1. Add first cache file CacheKey key1 = new SimpleCacheKey("foo"); int value1Size = 101; byte[] value1 = new byte[value1Size]; value1[80] = 'c'; // just so it's not all zeros for the equality test below. BinaryResource resource1 = mCache.insert(key1, WriterCallbacks.from(value1)); verifyListenerOnWriteAttempt(key1); String resourceId1 = verifyListenerOnWriteSuccessAndGetResourceId(key1, value1Size); BinaryResource resource1Again = mCache.getResource(key1); assertEquals(resource1, resource1Again); verifyListenerOnHit(key1, resourceId1); BinaryResource resource1Again2 = mCache.getResource(key1); assertEquals(resource1, resource1Again2); verifyListenerOnHit(key1, resourceId1); SimpleCacheKey missingKey = new SimpleCacheKey("nonexistent_key"); BinaryResource res2 = mCache.getResource(missingKey); assertNull(res2); verifyListenerOnMiss(missingKey); mCache.clearAll(); verify(mCacheEventListener).onCleared(); verifyNoMoreInteractions(mCacheEventListener); }
/** * Test to make sure that the same item stored with two different versions * of the cache will be stored with two different file names. * * @throws UnsupportedEncodingException */ @Test public void testVersioning() throws IOException { // Define data that will be written to cache CacheKey key = new SimpleCacheKey("version_test"); byte[] value = new byte[32]; value[0] = 'v'; // Set up cache with version == 1 DiskStorage storage1 = createDiskStorage(TESTCACHE_CURRENT_VERSION); DiskStorageCache cache1 = createDiskCache(storage1, false); // Write test data to cache 1 cache1.insert(key, WriterCallbacks.from(value)); // Get cached file BinaryResource resource1 = getResource(storage1, key); assertNotNull(resource1); // Set up cache with version == 2 DiskStorage storageSupplier2 = createDiskStorage(TESTCACHE_NEXT_VERSION); DiskStorageCache cache2 = createDiskCache(storageSupplier2, false); // Write test data to cache 2 cache2.insert(key, WriterCallbacks.from(value)); // Get cached file BinaryResource resource2 = getResource(storageSupplier2, key); assertNotNull(resource2); // Make sure filenames of the two file are different assertFalse(resource2.equals(resource1)); }
@Override public BinaryResource getResource(String resourceId, Object debugInfo) throws IOException { if (resourceId.equals(mPoisonResourceId)) { throw POISON_EXCEPTION; } return get().getResource(resourceId, debugInfo); }
/** * Performs disk cache read. In case of any exception null is returned. */ private PooledByteBuffer readFromDiskCache(final CacheKey key) throws IOException { try { FLog.v(TAG, "Disk cache read for %s", key.getUriString()); final BinaryResource diskCacheResource = mFileCache.getResource(key); if (diskCacheResource == null) { FLog.v(TAG, "Disk cache miss for %s", key.getUriString()); mImageCacheStatsTracker.onDiskCacheMiss(); return null; } else { FLog.v(TAG, "Found entry in disk cache for %s", key.getUriString()); mImageCacheStatsTracker.onDiskCacheHit(); } PooledByteBuffer byteBuffer; final InputStream is = diskCacheResource.openStream(); try { byteBuffer = mPooledByteBufferFactory.newByteBuffer(is, (int) diskCacheResource.size()); } finally { is.close(); } FLog.v(TAG, "Successful read from disk cache for %s", key.getUriString()); return byteBuffer; } catch (IOException ioe) { // TODO: 3697790 log failures // TODO: 5258772 - uncomment line below // mFileCache.remove(key); FLog.w(TAG, ioe, "Exception reading from cache for %s", key.getUriString()); mImageCacheStatsTracker.onDiskCacheGetFail(); throw ioe; } }
private void save() { try { ImageRequest imageRequest = ImageRequest.fromUri(mUrl); CacheKey cacheKey = DefaultCacheKeyFactory.getInstance().getEncodedCacheKey(imageRequest); BinaryResource resource = ImagePipelineFactory.getInstance().getMainDiskStorageCache().getResource(cacheKey); File file = ((FileBinaryResource) resource).getFile(); String fileName = mUrl; fileName = fileName.substring(fileName.lastIndexOf('/') + 1); if (mTitle != null) { fileName = mTitle + fileName; } File pic = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); File dir = new File(pic, "material/"); if (!dir.exists()) { dir.mkdirs(); } File renamed = new File(dir, fileName); if (!renamed.exists()) { renamed.createNewFile(); FileUtil.copy(file, renamed); } UI.showToast(this, getString(R.string.image_saved_to, renamed.getAbsolutePath())); // Snackbar.make(mDraweeView,R.string.image_is_saved, Snackbar.LENGTH_LONG); } catch (Exception ex) { Log.w("SHARE", "Sharing " + mUrl + " failed", ex); } }
/** * 图片是否已经存在了 */ public static boolean isCached(Context context, Uri uri) { ImagePipeline imagePipeline = Fresco.getImagePipeline(); DataSource<Boolean> dataSource = imagePipeline.isInDiskCache(uri); if (dataSource == null) { return false; } ImageRequest imageRequest = ImageRequest.fromUri(uri); CacheKey cacheKey = DefaultCacheKeyFactory.getInstance() .getEncodedCacheKey(imageRequest, context); BinaryResource resource = ImagePipelineFactory.getInstance() .getMainFileCache().getResource(cacheKey); return resource != null && dataSource.getResult() != null && dataSource.getResult(); }
/** * 本地缓存文件 */ public static File getCache(Context context, Uri uri) { if (!isCached(context, uri)) return null; ImageRequest imageRequest = ImageRequest.fromUri(uri); CacheKey cacheKey = DefaultCacheKeyFactory.getInstance() .getEncodedCacheKey(imageRequest, context); BinaryResource resource = ImagePipelineFactory.getInstance() .getMainFileCache().getResource(cacheKey); File file = ((FileBinaryResource) resource).getFile(); return file; }
@Override public BinaryResource getResource(String resourceId, Object debugInfo) throws IOException { return get().getResource(resourceId, debugInfo); }
private BinaryResource getResource( DiskStorage storage, final CacheKey key) throws IOException { return storage.getResource(CacheKeyUtil.getFirstResourceId(key), key); }
private BinaryResource getResource(final CacheKey key) throws IOException { return mStorage.getResource(CacheKeyUtil.getFirstResourceId(key), key); }
private byte[] getContents(BinaryResource resource) throws IOException { return ByteStreams.toByteArray(resource.openStream()); }
@Test public void testCacheFileWithIOException() throws IOException { CacheKey key1 = new SimpleCacheKey("aaa"); // Before inserting, make sure files not exist. final BinaryResource resource1 = getResource(key1); assertNull(resource1); // 1. Should not create cache files if IOException happens in the middle. final IOException writeException = new IOException(); try { mCache.insert( key1, new WriterCallback() { @Override public void write(OutputStream os) throws IOException { throw writeException; } }); fail(); } catch (IOException e) { assertNull(getResource(key1)); } verifyListenerOnWriteAttempt(key1); verifyListenerOnWriteException(key1, writeException); // 2. Test a read failure from DiskStorage CacheKey key2 = new SimpleCacheKey("bbb"); int value2Size = 42; byte[] value2 = new byte[value2Size]; value2[25] = 'b'; mCache.insert(key2, WriterCallbacks.from(value2)); verifyListenerOnWriteAttempt(key2); String resourceId2 = verifyListenerOnWriteSuccessAndGetResourceId(key2, value2Size); ((DiskStorageWithReadFailures) mStorage).setPoisonResourceId(resourceId2); assertNull(mCache.getResource(key2)); verifyListenerOnReadException(key2, DiskStorageWithReadFailures.POISON_EXCEPTION); assertFalse(mCache.probe(key2)); verifyListenerOnReadException(key2, DiskStorageWithReadFailures.POISON_EXCEPTION); verifyNoMoreInteractions(mCacheEventListener); }
@Override public BitmapRegionDecoder intercept(Chain chain) throws IOException { final Uri uri = chain.uri(); BitmapRegionDecoder decoder = chain.chain(uri); if (decoder != null){ return decoder; } if (UriUtil.isNetworkUri(uri)){ ImagePipeline imagePipeline = ImagePipelineFactory.getInstance().getImagePipeline(); ImageRequest request = ImageRequest.fromUri(uri); DataSource<CloseableReference<PooledByteBuffer>> dataSource = imagePipeline.fetchEncodedImage(request,null); try { CloseableReference<PooledByteBuffer> ref = DataSources.waitForFinalResult(dataSource); if (ref == null){ return null; } PooledByteBuffer result = ref.get(); if (BuildConfig.DEBUG) { Log.d("FrescoInterceptor", "从我这加载"); } try { InputStream inputStream = new PooledByteBufferInputStream(result); Closeables.closeQuietly(inputStream); return BitmapRegionDecoder.newInstance(inputStream,false); } catch (IOException e) { ImageRequest imageRequest=ImageRequest.fromUri(uri); CacheKey cacheKey= DefaultCacheKeyFactory.getInstance().getEncodedCacheKey(imageRequest,null); BinaryResource resource = ImagePipelineFactory.getInstance().getMainFileCache().getResource(cacheKey); File file=((FileBinaryResource)resource).getFile(); if (BuildConfig.DEBUG) { Log.d("FrescoInterceptor", file.getName()); } return Interceptors.fixJPEGDecoder(file,e); } } catch (Throwable throwable) { if (BuildConfig.DEBUG) { Log.d("FrescoInterceptor", "intercept: 加载失败了"); } throwable.printStackTrace(); return null; } } return null; }