Fresco相信大家都不陌生,是個很不錯的圖片加載器
最近做的需求有查看大圖保存圖片,保存圖片很簡單,但是保存gif圖就需要處理一下了。
之前google了好久,也沒有找到靠譜的答案,(還是API看的不夠仔細(xì) ~)
原理在Fresco 數(shù)據(jù)源和數(shù)據(jù)訂閱者
因為是查看大圖的時候保存圖片,所以其實沒有必要非從網(wǎng)絡(luò)去下載圖片了,內(nèi)存or磁盤中可能已經(jīng)有緩存,再去網(wǎng)絡(luò)下載,顯然是浪費(fèi)用戶的流量,所以我是這樣做的。。。
情況一:
如果你的應(yīng)用只有靜態(tài)圖片,那么
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());
情況二:
如果你的應(yīng)用有靜態(tài)圖片也有動態(tài)圖片(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,再做相應(yīng)的命名處理
}catch(Exception e) {
}finally{
Closeables.closeQuietly(is);
}
}finally{
CloseableReference.closeSafely(ref);
ref =null;
}
}
}
@Override
protected voidonFailureImpl(DataSource> dataSource) {
saveFail();
}
},CallerThreadExecutor.getInstance());
總結(jié)
現(xiàn)在開源項目特別多,大家也都盡可能的不去重復(fù)造輪子,但是使用一個好的開源框架,最好還是了解一下源碼的實現(xiàn),這樣在使用的過程中,遇到的任何問題,都有解釋的依據(jù)。
情況一中,對圖片做了解碼處理,如果不想要解碼,直接使用情況二的方式也是可以的。
- null是什么鬼
上圖中的null
是什么鬼
其實是需要傳遞的是context但是我們看源碼
發(fā)現(xiàn)我們在調(diào)用設(shè)置圖片是,底層傳遞的就是null,所以為了避免我們的context被無法控制的第三方框架一直引用而引發(fā)內(nèi)存泄露,我們這里還是不要把context傳遞過去了(畢竟不傳,也沒發(fā)現(xiàn)什么問題),至于為什么會有這個參數(shù),還是要多看源碼分析了。
-
保存到系統(tǒng)相冊的問題
前面的保存,我們是保存到sd卡中我們自己的目錄,但是如果要保存到系統(tǒng)相冊,大部分使用的方式:
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) {
}
這里有個問題,看源碼
系統(tǒng)默認(rèn)存儲的是jpeg格式,這樣如果保存GIF圖就悲劇了。。。
開始我是想,拿到系統(tǒng)相冊路徑,手動保存,但是有兩個問題
1、系統(tǒng)相冊路徑如何獲取(不同rom存儲的位置都不一樣)
2、自己保存,縮略圖怎么生成(系統(tǒng)保存到相冊的的insertImage默認(rèn)會保存一份縮略圖)
目前這塊我還沒找到更好的方式處理,找到后一定要記錄下來。。。
好了,我去寫代碼了。。。