Fresco相信大家都不陌生,是个很不错的图片加载器
最近做的需求有查看大图保存图片,保存图片很简单,但是保存gif图就需要处理一下了。
之前google了好久,也没有找到靠谱的答案,(还是API看的不够仔细 ~)
原理在Fresco 数据源和数据订阅者
因为是查看大图的时候保存图片,所以其实没有必要非从网络去下载图片了,内存or磁盘中可能已经有缓存,再去网络下载,显然是浪费用户的流量,所以我是这样做的。。。
情况一:
如果你的应用只有静态图片,那么
DataSource> dataSource1 = imagePipeline.fetchDecodedImage(imageRequest, null);dataSource1.subscribe(new BaseBitmapDataSubscriber() { @Override protected void onNewResultImpl(Bitmap bitmap) { //get bitmap } @Override protected void onFailureImpl(DataSource> 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());
总结
现在开源项目特别多,大家也都尽可能的不去重复造轮子,但是使用一个好的开源框架,最好还是了解一下源码的实现,这样在使用的过程中,遇到的任何问题,都有解释的依据。
情况一中,对图片做了解码处理,如果不想要解码,直接使用情况二的方式也是可以的。
null是什么鬼
上图中的null是什么鬼
其实是需要传递的是context但是我们看源码
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) {
}
这里有个问题,看源码
insertImage
系统默认存储的是jpeg格式,这样如果保存GIF图就悲剧了。。。
开始我是想,拿到系统相册路径,手动保存,但是有两个问题
1、系统相册路径如何获取(不同rom存储的位置都不一样)
2、自己保存,缩略图怎么生成(系统保存到相册的的insertImage默认会保存一份缩略图)
目前这块我还没找到更好的方式处理,找到后一定要记录下来。。。
好了,我去写代码了。。。