今天在微信預覽大圖時,發現其在無網絡的狀況下也能夠保存圖片,我以爲這是個常見的需求,因此動手實現相似的需求,中間也踩了挺多坑,因此跟你們一塊兒分享我踩過的坑。數組
=============分割線============緩存
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視頻,壓的很差,見諒!