亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Android優(yōu)化查詢加載大數(shù)量的本地相冊圖片

 更新時間:2016年10月25日 14:48:36   作者:丿天下丶第一  
本文介紹了Android優(yōu)化查詢加載大數(shù)量的本地相冊圖片,可以方便的照片的查詢,,感興趣的小伙伴們可以參考一下。

一、概述

講解優(yōu)化查詢相冊圖片之前,我們先來看下PM提出的需求,PM的需求很簡單,就是要做一個類似微信的本地相冊圖片查詢控件,主要包含兩個兩部分:

  • 進入圖片選擇頁面就要顯示出手機中所有的照片,包括系統(tǒng)相冊圖片和其他目錄下的所有圖片,并按照時間倒敘排列
  • 切換相冊功能,切換相冊頁面列出手機中所有的圖片目錄列表,并且顯示出每個目錄下所有的圖片個數(shù)以及封面圖片

這兩個需求看似簡單,實則隱藏著一系列的性能優(yōu)化問題。在做優(yōu)化之前,我們調(diào)研了一些其他比較出名的app在加載大數(shù)量圖片的性能表現(xiàn)(gif錄制的不夠清晰,但展示問題已經(jīng)夠了):

下面測試了幾個常用軟件

微信:
微信的圖片查詢速度還是非常快的,基本上進入圖片選擇頁面,相冊數(shù)據(jù)就已經(jīng)查出來了,包括各個圖片目錄下圖片的個數(shù)和封面圖片的url,這個體驗還是比較好的。

新浪微博:
相比較微信來說,新浪微博做的體驗就比較差了,進入圖片選擇頁面后,先是黑屏然后是白屏,連個進度條都沒有,讓用戶以為app死掉了,等過一段時間才顯示出來,這個體驗較差

QQ:
QQ一上來是加載的最近100張照片,這個速度非???,但是進入Camera相冊(有5000多張)后,有一個進度條等待,我體驗了下,等待的時間還是比較長的,這個體驗比新浪微博稍微好點,比微信差

閑魚:
閑魚是做的最爛的一個,一上來是卡死四五秒,然后是黑屏兩三秒,最后才顯示出來

二、綜合對比

經(jīng)過綜合對比后,就微信做的還比較好,基本上進入相冊頁面就能展示出所有照片,相冊目錄也非??斓恼故境鰜恚。?!

經(jīng)過我們的調(diào)研,發(fā)現(xiàn)微信是采用循環(huán)分頁加載策略,我們優(yōu)化的思路也是采用這種策略,先看優(yōu)化后的效果圖:

進入圖片選擇頁面,圖片能夠非常快的顯示出來,進入更換相冊頁面,圖片目錄也能非??斓娘@示出來,這里沒有像微信一樣做圖片目錄的緩存:一是因為查詢速度非???,基本上不到2秒就加載出來了,二是能夠?qū)崟r刷新出相冊的最新數(shù)據(jù)

頻繁的切換各個相冊目錄,圖片都能非??焖俚牟樵兂鰜?,體驗還是不錯的?。?!

三、優(yōu)化實現(xiàn)

優(yōu)化查詢相冊目錄

因為要列舉出所有的相冊目錄列表,這里沒有其他好的辦法,直接請求ContentResolver的query方法來查詢,這里為了加速查詢,去掉了while循環(huán)中一些耗時的判斷,將一些檢測圖片是否判斷的邏輯移到外面去,具體用的時候再去判斷

查詢圖片的URI

MediaStore.Images.Media.EXTERNAL_CONTENT_URI

因為我們只查詢圖片url和圖片所在的目錄

String[] projection = {MediaStore.Images.ImageColumns.DATA, MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME};

PM要求相冊按照圖片的時間倒敘排列,圖片的創(chuàng)建、修改會影響其所在目錄的排序,排序按時間倒敘排列

String sortOrder = MediaStore.Images.Media.DATE_TAKEN + " DESC ";

根據(jù)這些查詢條件,經(jīng)過query之后得到一個Cursor,這個cursor里面就包含我們所需要的所有圖片的信息,然后我們while循環(huán)遍歷這個cursor,在while循環(huán)中一定不能有耗時操作

//一個輔助集合,防止同一目錄被掃描多次
HashSet<String> dirPaths = new HashSet<String>();

while (cursor.moveToNext()) {
  // 獲取圖片的路徑
  String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA));
  String bucketName = cursor.getString(cursor.getColumnIndex(MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME));

  if (TextUtils.isEmpty(allFolderItem.coverImagePath)) {
    allFolderItem.coverImagePath = path;
  }

  File parentFile = new File(path).getParentFile();
  if (parentFile == null) continue;

  String dirPath = parentFile.getAbsolutePath();

  PicFolderItem folderItem = null;
  // 利用一個HashSet防止多次掃描同一個文件夾(不加這個判斷,圖片多起來還是相當(dāng)恐怖的~~)
  if (dirPaths.contains(dirPath)) {
    continue;
  } else {
    dirPaths.add(dirPath);

    boolean isNew = true;
    //判斷一下是否dirPath不同,但是bucketName相同
    for (PicFolderItem item : picList) {
      if (item.name.equals(bucketName)) {
        folderItem = item;
        item.addParentPath(dirPath);
        isNew = false;
        break;
      }
    }

    if (isNew) {
      folderItem = new PicFolderItem();
      folderItem.coverImagePath = path;
      folderItem.name = bucketName;
      folderItem.addParentPath(dirPath);
    }
  }

  String[] array = parentFile.list(new FilenameFilter() {
    @Override
    public boolean accept(File dir, String filename) {
      if (filename.endsWith(".jpg")
          || filename.endsWith(".png")
          || filename.endsWith(".jpeg"))
        return true;
      return false;
    }
  });

  int arrayCount = array == null ? 0 : array.length;
  folderItem.count += arrayCount;
  if (!picList.contains(folderItem) && arrayCount > 0) {
    picList.add(folderItem);
  }
}

這樣就能非常快速的查詢出手機中所有的圖片目錄、目錄的圖片張數(shù)以及封面圖url。這里主要優(yōu)化了三點:

while循環(huán)中去除耗時判斷

之前的代碼中存在判斷文件圖片是否存在的代碼:

 public static boolean isFileExist(String path) {
  File file = new File(path);
  if (file == null || !file.exists()) {
    return false;
  }
  return true;
  }

這段代碼放到while循環(huán)中是很恐怖的,我測試了下,5000多張圖片都要檢測的話總時間會增加三四秒。這個判斷可以放到外面去,具體操作哪一個圖片的時候再做具體的業(yè)務(wù)判斷!

防止一個圖片文件夾被掃描多次

這里添加了一個變量來存儲已經(jīng)掃描過的圖片目錄,已經(jīng)掃描的就不在處理了:

//一個輔助集合,防止統(tǒng)一目錄查詢多次
HashSet<String> dirPaths = new HashSet<String>();

這塊優(yōu)化了之后效果還是很明顯的,相同的目錄不會掃描多次!

獲取圖片目錄下圖片個數(shù)

String[] array = parentFile.list(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String filename) {
              if (filename.endsWith(".jpg")
                  || filename.endsWith(".png")
                  || filename.endsWith(".jpeg"))
                return true;
              return false;
            }
          });

這個file.list()方法內(nèi)部是一個native方法,查詢效率非??欤。?!

當(dāng)然獲取某個目錄下的圖片有多少張也可以通過cursor查詢的方式來獲?。?!!

查詢某個相冊目錄下的所有照片

在介紹查詢目錄下的照片之前,我們先介紹下我們查詢圖片的兩種策略,一種是針對目錄下圖片比較多的,動不動就上千上萬張的那種;另一種是那種目錄下圖片比較少的,就幾百張圖片

一次加載策略

當(dāng)目錄下圖片數(shù)量小于1000張時采用file.list這個native方法來一次加載所有圖片,這個native查詢效率非??欤锨垐D片都是秒級查詢出來

循環(huán)分頁加載策略

當(dāng)圖片數(shù)量大于等于1000張時采用循環(huán)分頁加載策略,這種策略專門針對圖片數(shù)量特別多的情況,通過分頁的方式先把第一頁的圖片加載出來,讓用戶能第一眼看到最新的圖片,然后后臺異步循環(huán)的查詢下一頁圖片,直到所有圖片都查詢完成,這也是微信的查詢相冊策略。

一次加載策略實現(xiàn)

我們這里看下一次加載完策略實現(xiàn)代碼,首先通過File的list方法將后綴為圖片格式的文件過濾出來,返回一個圖片路徑數(shù)組

File dirFile = new File(dir);
String[] list = dirFile.list(new FilenameFilter() {
  @Override
  public boolean accept(File dir, String filename) {
    if (filename.endsWith(".jpg") || filename.endsWith(".png")
        || filename.endsWith(".jpeg"))
      return true;
    return false;
  }
});

因為我們要的是按時間倒敘進行排列的數(shù)組,所以要對上面查詢出來的數(shù)組進行排序,這里用到了File文件lastModified方法

Collections.sort(strings, new Comparator<String>() {
        @Override
        public int compare(String lhs, String rhs) {
          Long time1 = new File(lhs).lastModified();
          Long time2 = new File(rhs).lastModified();
          return time2.compareTo(time1);
        }
        });

循環(huán)分頁加載策略實現(xiàn)

這個策略借鑒了微信,通過分頁的方式來一頁一頁的加載圖片,直到所有的圖片都加載完成。

這里的核心就是查詢條件,將你要查詢的某個目錄添加到查詢參數(shù)中

String selection = MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME + " = '" + 目錄名稱 + "' ";

這個selection一定不能寫錯,不然查詢不出來

因為要分頁,sortOrder不是簡單的按照時間倒敘來排了

String sortOrder = MediaStore.Images.Media.DATE_TAKEN + " DESC limit " + PAGE_SIZE + " offset " + pageIndex * PAGE_SIZE;

最后對Cursor進行循環(huán)遍歷拿到我們要的圖片路徑

PAGE_SIZE是個常量,表示我們要一次查詢多少條,我們這里定的是200,一次查詢200條數(shù)據(jù),pageIndex是查詢第幾頁,從0開始

一開始的時候查詢第一頁的數(shù)據(jù),當(dāng)查詢的數(shù)據(jù)列表大小大于等于我們要查詢的PageSize大小時,我們就認為有下一頁,pageIndex加1循環(huán)查詢下一頁,直到查詢的列表大小小于PageSize。

經(jīng)過上面幾步優(yōu)化后,加載本地相冊圖片基本上就沒有什么問題了。我們經(jīng)過真機測試,圖片5549張,都能夠非??焖俚牟樵兂鰜恚氨任⑿藕蛨D庫。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論