Android使用Fresco之下載圖片(包括GIF圖)

weixin_34107955發表於2016-09-19

Fresco相信大家都不陌生,是個很不錯的圖片載入器
最近做的需求有檢視大圖儲存圖片,儲存圖片很簡單,但是儲存gif圖就需要處理一下了。
之前google了好久,也沒有找到靠譜的答案,(還是API看的不夠仔細 ~)
原理在Fresco 資料來源和資料訂閱者
因為是檢視大圖的時候儲存圖片,所以其實沒有必要非從網路去下載圖片了,記憶體or磁碟中可能已經有快取,再去網路下載,顯然是浪費使用者的流量,所以我是這樣做的。。。


情況一:

如果你的應用只有靜態圖片,那麼
DataSource<CloseableReference<CloseableImage>> dataSource1 = imagePipeline.fetchDecodedImage(imageRequest, null);dataSource1.subscribe(new BaseBitmapDataSubscriber() { @Override protected void onNewResultImpl(Bitmap bitmap) { //get bitmap } @Override protected void onFailureImpl(DataSource<CloseableReference<CloseableImage>> dataSource) { }}, CallerThreadExecutor.getInstance());


情況二:

如果你的應用有靜態圖片也有動態圖片(GIF)

DataSource> dataSource =
imagePipeline.fetchEncodedImage(imageRequest, null);
dataSource.subscribe(newBaseDataSubscriber>() {
@Override
protected voidonNewResultImpl(DataSource> dataSource) {
if(!dataSource.isFinished()) {
saveFail();
return;
}
CloseableReference ref = dataSource.getResult();
if(ref !=null) {
try{
PooledByteBuffer result = ref.get();
InputStream is =newPooledByteBufferInputStream(result);
try{
ByteArrayOutputStream bos =newByteArrayOutputStream(1000);
byte[] b =new byte[1000];
intn;
while((n = is.read(b)) != -1) {
bos.write(b,0,n);
}
is.close();
bos.close();
savePic(url,bos.toByteArray());//通過byte檔案頭,判斷是否是gif,再做相應的命名處理
}catch(Exception e) {
}finally{
Closeables.closeQuietly(is);
}
}finally{
CloseableReference.closeSafely(ref);
ref =null;
}
}
}
@Override
protected voidonFailureImpl(DataSource> dataSource) {
saveFail();
}
},CallerThreadExecutor.getInstance());

總結

現在開源專案特別多,大家也都儘可能的不去重複造輪子,但是使用一個好的開源框架,最好還是瞭解一下原始碼的實現,這樣在使用的過程中,遇到的任何問題,都有解釋的依據。

  • 情況一中,對圖片做了解碼處理,如果不想要解碼,直接使用情況二的方式也是可以的。

  • 2461049-f0a66e5bad8745f6.png
    null是什麼鬼

上圖中的null是什麼鬼
其實是需要傳遞的是context但是我們看原始碼

2461049-5062b6cec6501182.png
simpleDraweeView.setImageURI(getImageUri(path)

發現我們在呼叫設定圖片是,底層傳遞的就是null,所以為了避免我們的context被無法控制的第三方框架一直引用而引發記憶體洩露,我們這裡還是不要把context傳遞過去了(畢竟不傳,也沒發現什麼問題),至於為什麼會有這個引數,還是要多看原始碼分析了。

  • 儲存到系統相簿的問題
    前面的儲存,我們是儲存到sd卡中我們自己的目錄,但是如果要儲存到系統相簿,大部分使用的方式:
File file =newFile(filePath);
String uri =null;
String systemFilepath = filePath;
try{
uri = MediaStore.Images.Media.insertImage(context.getContentResolver(),file.getAbsolutePath(),"","");
systemFilepath =getFilePathByContentResolver(context,Uri.parse(uri));
MediaScannerConnection.scanFile(context, newString[]{systemFilepath}, null, null);
FileHelper.DataDir.deleteFileOrDir(file);
returnsystemFilepath;
}catch(Throwable e) {
}

這裡有個問題,看原始碼

2461049-39c539eacda3fd79.png
insertImage

系統預設儲存的是jpeg格式,這樣如果儲存GIF圖就悲劇了。。。
開始我是想,拿到系統相簿路徑,手動儲存,但是有兩個問題
1、系統相簿路徑如何獲取(不同rom儲存的位置都不一樣)
2、自己儲存,縮圖怎麼生成(系統儲存到相簿的的insertImage預設會儲存一份縮圖)
目前這塊我還沒找到更好的方式處理,找到後一定要記錄下來。。。

好了,我去寫程式碼了。。。

相關文章