溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

Android中怎么保存多張圖片到本地

發(fā)布時(shí)間:2021-08-07 15:02:45 來(lái)源:億速云 閱讀:130 作者:Leah 欄目:編程語(yǔ)言

Android中怎么保存多張圖片到本地,很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來(lái)學(xué)習(xí)下,希望你能有所收獲。

01.實(shí)際開(kāi)發(fā)保存圖片遇到的問(wèn)題

業(yè)務(wù)需求

在素材list頁(yè)面的九宮格素材中,展示網(wǎng)絡(luò)請(qǐng)求加載的圖片。如果用戶(hù)點(diǎn)擊保存按鈕,則保存若干張圖片到本地。具體做法是,使用glide加載圖片,然后設(shè)置listener監(jiān)聽(tīng),在圖片請(qǐng)求成功onResourceReady后,將圖片資源resource保存到集合中。這個(gè)時(shí)候,如果點(diǎn)擊保存控件,則循環(huán)遍歷圖片資源集合保存到本地文件夾。

具體做法代碼展示

這個(gè)時(shí)候直接將請(qǐng)求網(wǎng)絡(luò)的圖片轉(zhuǎn)化成bitmap,然后存儲(chǔ)到集合中。然后當(dāng)點(diǎn)擊保存按鈕的時(shí)候,將會(huì)保存該組集合中的多張圖片到本地文件夾中。

//bitmap圖片集合private ArrayList<Bitmap> bitmapArrayList = new ArrayList<>();RequestOptions requestOptions = new RequestOptions() .transform(new GlideRoundTransform(mContext, radius, cornerType));GlideApp.with(mIvImg.getContext()) .asBitmap() .load(url) .listener(new RequestListener<Bitmap>() {  @Override  public boolean onLoadFailed(@Nullable GlideException e, Object model,     Target<Bitmap> target, boolean isFirstResource) {  return true;  }  @Override  public boolean onResourceReady(Bitmap resource, Object model, Target<Bitmap> target,      DataSource dataSource, boolean isFirstResource) {  bitmapArrayList.add(resource);  return false;  } }) .apply(requestOptions) .placeholder(ImageUtils.getDefaultImage()) .into(mIvImg);   //循環(huán)遍歷圖片資源集合,然后開(kāi)始保存圖片到本地文件夾mBitmap = bitmapArrayList.get(i);savePath = FileSaveUtils.getLocalImgSavePath();FileOutputStream fos = null;try { File filePic = new File(savePath); if (!filePic.exists()) { filePic.getParentFile().mkdirs(); filePic.createNewFile(); } fos = new FileOutputStream(filePic); // 100 圖片品質(zhì)為滿(mǎn) mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);} catch (IOException e) { e.printStackTrace(); return null;} finally { if (fos != null) { try {  fos.flush();  fos.close(); } catch (IOException e) {  e.printStackTrace(); } } //刷新相冊(cè) if (isScanner) { scanner(context, savePath); }}

遇到的問(wèn)題

保存圖片到本地后,發(fā)現(xiàn)圖片并不是原始的圖片,而是展現(xiàn)在view控件上被裁切的圖片,也就是ImageView的尺寸大小圖片。

為什么會(huì)遇到這種問(wèn)題

如果你傳遞一個(gè)ImageView作為.into()的參數(shù),Glide會(huì)使用ImageView的大小來(lái)限制圖片的大小。例如如果要加載的圖片是1000x1000像素,但是ImageView的尺寸只有250x250像素,Glide會(huì)降低圖片到小尺寸,以節(jié)省處理時(shí)間和內(nèi)存。

在設(shè)置into控件后,也就是說(shuō),在onResourceReady方法中返回的圖片資源resource,實(shí)質(zhì)上不是你加載的原圖片,而是ImageView設(shè)定尺寸大小的圖片。所以保存之后,你會(huì)發(fā)現(xiàn)圖片變小了。

那么如何解決問(wèn)題呢?

第一種做法:九宮格圖片控件展示的時(shí)候會(huì)加載網(wǎng)絡(luò)資源,然后加載圖片成功后,則將資源保存到集合中,點(diǎn)擊保存則循環(huán)存儲(chǔ)集合中的資源。這種做法只會(huì)請(qǐng)求一個(gè)網(wǎng)絡(luò)。由于開(kāi)始

第二種做法:九宮格圖片控件展示的時(shí)候會(huì)加載網(wǎng)絡(luò)資源,點(diǎn)擊保存九宮格圖片的時(shí)候,則依次循環(huán)請(qǐng)求網(wǎng)絡(luò)圖片資源然后保存圖片到本地,這種做法會(huì)請(qǐng)求兩次網(wǎng)絡(luò)。

02.直接用http請(qǐng)求圖片并保存本地

http請(qǐng)求圖片

/** * 請(qǐng)求網(wǎng)絡(luò)圖片 * @param url   url */private static long time = 0;public static InputStream HttpImage(String url) { long l1 = System.currentTimeMillis(); URL myFileUrl = null; Bitmap bitmap = null; HttpURLConnection conn = null; InputStream is = null; try { myFileUrl = new URL(url); } catch (MalformedURLException e) { e.printStackTrace(); } try { conn = (HttpURLConnection) myFileUrl.openConnection(); conn.setConnectTimeout(10000); conn.setReadTimeout(5000); conn.setDoInput(true); conn.connect(); is = conn.getInputStream(); } catch (IOException e) { e.printStackTrace(); } finally { try {  if (is != null) {  is.close();  conn.disconnect();  } } catch (IOException e) {  e.printStackTrace(); } long l2 = System.currentTimeMillis(); time = (l2-l1) + time; LogUtils.e("毫秒值"+time); //保存 } return is;}```

保存到本地

InputStream inputStream = HttpImage( "https://cache.yisu.com/upload/information/20201211/272/44845.jpg");String localImgSavePath = FileSaveUtils.getLocalImgSavePath();File imageFile = new File(localImgSavePath);if (!imageFile.exists()) { imageFile.getParentFile().mkdirs(); try { imageFile.createNewFile(); } catch (IOException e) { e.printStackTrace(); }}FileOutputStream fos = null;BufferedInputStream bis = null;try { fos = new FileOutputStream(imageFile); bis = new BufferedInputStream(inputStream); byte[] buffer = new byte[1024]; int len; while ((len = bis.read(buffer)) != -1) { fos.write(buffer, 0, len); }} catch (Exception e) { e.printStackTrace();} finally { try { if (bis != null) {  bis.close(); } if (fos != null) {  fos.close(); } } catch (IOException e) { e.printStackTrace(); }}

03.用glide下載圖片保存本地

glide下載圖片

File file = Glide.with(ReflexActivity.this) .load(url.get(0)) .downloadOnly(500, 500) .get();

保存到本地

String localImgSavePath = FileSaveUtils.getLocalImgSavePath();File imageFile = new File(localImgSavePath);if (!imageFile.exists()) { imageFile.getParentFile().mkdirs(); imageFile.createNewFile();}copy(file,imageFile);/** * * @param source 輸入文件 * @param target 輸出文件 */public static void copy(File source, File target) { FileInputStream fileInputStream = null; FileOutputStream fileOutputStream = null; try { fileInputStream = new FileInputStream(source); fileOutputStream = new FileOutputStream(target); byte[] buffer = new byte[1024]; while (fileInputStream.read(buffer) > 0) {  fileOutputStream.write(buffer); } } catch (Exception e) { e.printStackTrace(); } finally { try {  if (fileInputStream != null) {  fileInputStream.close();  }  if (fileOutputStream != null) {  fileOutputStream.close();  } } catch (IOException e) {  e.printStackTrace(); } }}```

04.如何實(shí)現(xiàn)連續(xù)保存多張圖片

思路:循環(huán)子線程

可行(不推薦), 如果我要下載9個(gè)圖片,將子線程加入for循環(huán)內(nèi),并最終呈現(xiàn)。  有嚴(yán)重缺陷,線程延時(shí),圖片順序不能做保證。如果是線程套線程的話,第一個(gè)子線程結(jié)束了,嵌套在該子線程f的or循環(huán)內(nèi)的子線程還沒(méi)結(jié)束,從而主線程獲取不到子線程里獲取的圖片。  還有就是如何判斷所有線程執(zhí)行完畢,比如所有圖片下載完成后,吐司下載完成。

不建議的方案

創(chuàng)建一個(gè)線程池來(lái)管理線程,關(guān)于線程池封裝庫(kù),可以看線程池簡(jiǎn)單封裝

這種方案不知道所有線程中請(qǐng)求圖片是否全部完成,且不能保證順序。

ArrayList<String> images = new ArrayList<>();for (String image : images){ //使用該線程池,及時(shí)run方法中執(zhí)行異常也不會(huì)崩潰 PoolThread executor = BaseApplication.getApplication().getExecutor(); executor.setName("getImage"); executor.execute(new Runnable() {  @Override  public void run() {   //請(qǐng)求網(wǎng)絡(luò)圖片并保存到本地操作  } });}

推薦解決方案

ArrayList<String> images = new ArrayList<>();ApiService apiService = RetrofitService.getInstance().getApiService();//注意:此處是保存多張圖片,可以采用異步線程ArrayList<Observable<Boolean>> observables = new ArrayList<>();final AtomicInteger count = new AtomicInteger();for (String image : images){ observables.add(apiService.downloadImage(image)   .subscribeOn(Schedulers.io())   .map(new Function<ResponseBody, Boolean>() {    @Override    public Boolean apply(ResponseBody responseBody) throws Exception {     saveIo(responseBody.byteStream());     return true;    }   }));}// observable的merge 將所有的observable合成一個(gè)Observable,所有的observable同時(shí)發(fā)射數(shù)據(jù)Disposable subscribe = Observable.merge(observables).observeOn(AndroidSchedulers.mainThread())  .subscribe(new Consumer<Boolean>() {   @Override   public void accept(Boolean b) throws Exception {    if (b) {     count.addAndGet(1);     Log.e("yc", "download is succcess");    }   }  }, new Consumer<Throwable>() {   @Override   public void accept(Throwable throwable) throws Exception {    Log.e("yc", "download error");   }  }, new Action() {   @Override   public void run() throws Exception {    Log.e("yc", "download complete");    // 下載成功的數(shù)量 和 圖片集合的數(shù)量一致,說(shuō)明全部下載成功了    if (images.size() == count.get()) {     ToastUtils.showRoundRectToast("保存成功");    } else {     if (count.get() == 0) {      ToastUtils.showRoundRectToast("保存失敗");     } else {      ToastUtils.showRoundRectToast("因網(wǎng)絡(luò)問(wèn)題 保存成功" + count + ",保存失敗" + (images.size() - count.get()));     }    }   }  }, new Consumer<Disposable>() {   @Override   public void accept(Disposable disposable) throws Exception {    Log.e("yc","disposable");   }  });      private void saveIo(InputStream inputStream){ String localImgSavePath = FileSaveUtils.getLocalImgSavePath(); File imageFile = new File(localImgSavePath); if (!imageFile.exists()) {  imageFile.getParentFile().mkdirs();  try {   imageFile.createNewFile();  } catch (IOException e) {   e.printStackTrace();  } } FileOutputStream fos = null; BufferedInputStream bis = null; try {  fos = new FileOutputStream(imageFile);  bis = new BufferedInputStream(inputStream);  byte[] buffer = new byte[1024];  int len;  while ((len = bis.read(buffer)) != -1) {   fos.write(buffer, 0, len);  } } catch (Exception e) {  e.printStackTrace(); } finally {  try {   if (bis != null) {    bis.close();   }   if (fos != null) {    fos.close();   }  } catch (IOException e) {   e.printStackTrace();  }  //刷新相冊(cè)代碼省略…… }}

看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注億速云行業(yè)資訊頻道,感謝您對(duì)億速云的支持。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI