今天在微信预览大图时,发现其在无网络的状况下也能够保存图片,我以为这是个常见的需求,因此动手实现相似的需求,中间也踩了挺多坑,因此跟你们一块儿分享我踩过的坑。数组
=============分割线============缓存
Glide4.x如下,加载图片的方式为bash
Glide.with(context)
.load(obj)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(imageView);复制代码
Glide4.x以上时,为微信
RequestOptions requestOptions = new RequestOptions()
.centerCrop()
.dontAnimate()
.diskCacheStrategy(DiskCacheStrategy.ALL);
Glide.with(context)
.load(obj)
.apply(requestOptions)
.into(iv);复制代码
这里有个注意点,diskCacheStrategy方法的缓存策略须要指定为DiskCacheStrategy.ALL或者DiskCacheStrategy.SOURCE,若是指定的缓存策略为DiskCacheStrategy.NONE,是获取不到缓存图的。网络
咱们首先须要获取缓存的File,Glide由于版本不一样,获取File的方式也不一样app
Glide4.x如下获取的方法为ide
File file = Glide.with(context)
.load(imgUrl)
.downloadOnly(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
.get();复制代码
Glide4.x以上时,为spa
File file = Glide.with(context)
.download(imgUrl)
.submit()
.get();复制代码
得到File后,这只是个文件,存在系统data目录下,咱们须要将File复制到sd卡的目录下,并重命名为.jpg文件。线程
复制代码
String fileParentPath =
Environment.getExternalStorageDirectory().getAbsolutePath() + "/XingTu/Image";
File appDir = new File(fileParentPath);
if (!appDir.exists()) {
appDir.mkdirs();
}
//得到原文件流
FileInputStream fis = new FileInputStream(file);
//保存的文件名
String fileName = "xt" + System.currentTimeMillis() + ".jpg";
//目标文件
File targetFile = new File(appDir, fileName);
//输出文件流
FileOutputStream fos = new FileOutputStream(targetFile);
// 缓冲数组
byte[] b = new byte[1024 * 8];
while (fis.read(b) != -1) {
fos.write(b);
}
fos.flush();
fis.close();
fos.close();复制代码
首先建立要保存路径的文件appDir,而后建立目标文件targetFile,接着建立输入输出流,经过while循环输出文件,最后别忘了调用flush和close方法释放资源。code
咱们保存玩图片后,须要通知系统相册刷新,不然是找不到保存的图片的。
关于通知系统相册更新,有两种方法。
第一,直接发送广播
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri uri = Uri.fromFile(file);
intent.setData(uri);
context.sendBroadcast(intent);复制代码
第二,使用MediaScannerConnection
//扫描媒体库
String extension = MimeTypeMap.getFileExtensionFromUrl(targetFile.getAbsolutePath());
String mimeTypes = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
MediaScannerConnection.scanFile(context, new String[]{targetFile.getAbsolutePath()},
new String[]{mimeTypes},null);复制代码
上面两种方法都能达到更新效果,可是查看了其余博客,有人说第一种方法某些状况下无效,具体我没有深究,这里推荐使用第二种方法更新。
public void saveImgToGallery(final Context context, final String imgUrl){
Observable.create((ObservableOnSubscribe<File>) emitter -> {
//Glide提供了一个download() 接口来获取缓存的图片文件,
// 可是前提必需要设置diskCacheStrategy方法的缓存策略为
// DiskCacheStrategy.ALL或者DiskCacheStrategy.SOURCE,
// 还有download()方法须要在子线程里进行
File file = Glide.with(context)
.download(imgUrl)
.submit()
.get();
String fileParentPath =
Environment.getExternalStorageDirectory().getAbsolutePath() + "/XingTu/Image";
File appDir = new File(fileParentPath);
if (!appDir.exists()) {
appDir.mkdirs();
}
//得到原文件流
FileInputStream fis = new FileInputStream(file);
//保存的文件名
String fileName = "xt" + System.currentTimeMillis() + ".jpg";
//目标文件
File targetFile = new File(appDir, fileName);
//输出文件流
FileOutputStream fos = new FileOutputStream(targetFile);
// 缓冲数组
byte[] b = new byte[1024 * 8];
while (fis.read(b) != -1) {
fos.write(b);
}
fos.flush();
fis.close();
fos.close();
//扫描媒体库
String extension = MimeTypeMap.getFileExtensionFromUrl(targetFile.getAbsolutePath());
String mimeTypes = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
MediaScannerConnection.scanFile(context, new String[]{targetFile.getAbsolutePath()},
new String[]{mimeTypes},null);
emitter.onNext(targetFile);
})
.subscribeOn(Schedulers.io()) //发送事件在io线程
.observeOn(AndroidSchedulers.mainThread())//最后切换主线程提示结果
.subscribe(file -> ToastUtil.showToast("保存图片成功"),
throwable -> ToastUtil.showToast("保存失败"));
}复制代码
总结:这是一个常见的需求,虽然代码很短,可是涉及到三个大的知识点,须要注重日常的积累,在遇到问题时首先冷静思考,而不是内心mmp,这样才能有效解决问题。
第一次写博客,若是有不对的地方欢迎一块儿交流。
最后放一个操做的gif视频,压的很差,见谅!