2017-08-14 45 views
1

我不清楚如何在緩存方面處理Android圖像。假設我有一個應用程序 ,這個應用程序的深度爲3級(所以它有3個活動在 之間互相推送)。Android - 處理作爲解決方案一部分的圖像和下載的圖像

如果我的3個活動中的每一個在所有3個活動的工具欄中顯示3個圖像,我的理解是相同的3個圖像將在內存中加載3次。這導致9張圖像記憶雖然只有3張圖像,但它們只是多次加載 。

另外,假設我的主要活動有一個ListView,顯示有關通過網絡檢索的文檔的信息。

每個列表視圖項被定製爲顯示3個信息:

  • 表示類型的文檔的圖像(即txt文件,.PDF,.DOCX,的.js,...)
  • 代表標題
  • 字符串代表的一些描述

如果上面的ListView加載一個字符串萬件(每一個代表一個文件),並承擔一切都是一個Word文檔,然後.D所有萬張圖片ocx類型被下載,但它確實只是我需要的一個圖像。這似乎是顯而易見的網絡帶寬和內存浪費,我只想下載一張圖片並使用它一百萬次,而不是下載數百萬張圖片,每次只使用一次。

因此,在這樣的情況下,我不知道我需要什麼樣的圖像,因此沒有它在圖像資產,但依靠下載的圖像來顯示文檔類型,是否有某種緩存策略,我可以用來避免不得不下載相同的圖像百萬次?

它是否已經由Android提供?

UPDATE

以我的工具欄的圖像的上面的例子中,這些是Android的資源的圖像(因此,圖形)。所以,對於這些,我相信這些默認緩存?

然而,ListView的圖像是從網絡下載,所以在我的例子與以上組成3個視圖(一個圖像和2個標籤),則圖像將在同一時間的ListView下載定製的ListViewItem正在圖像渲染。我提供了一個簡單的ListView項目只有3個視圖,但它可以是10個視圖(比如4個圖像和6個標籤)。重點是在ListView的渲染過程中從Web下載一個圖像。由於該圖像可能重複,如何避免下載相同的圖像,但使用緩存的圖像?

回答

1

首先對項目

ListView名單並不在你認爲這樣一個低效的方式工作。但如果你真的關心效率和處理真正大量的數據列表,建議使用RecyclerView。與here的比較有很好的討論和答案。

如果您計劃處理數千個文檔的列表,其中包含某些有限的文檔類型圖標集合,最佳做法是創建一個位圖HashMap,您將鏈接到特定的列表項目(無論您將會選擇使用:RecyclerViewListView)。

下面是一個簡單的例子(這是不正確的java,只給一個想法)與列表視圖適配器類:

public class DocumentsListAdapter extends ArrayAdapter<String> { 
    private final HashMap<String, Bitmap> docIcons = HashMap<String, Bitmap>() 
    private final Activity mContext; 
    private final List<String> mItems; 

    public DocumentsListAdapter(Activity context, List<String> items) { 
     docIcons.put("docx", loadDocBitmapFromDisk()); 
     docIcons.put("xls", loadXlsBitmapFromDisk()); 
     docIcons.put("pdf", loadPdfBitmapFromDisk()); 
     // and so on... 
     mItems = items; 
     mContext = context; 

    } 

    @Override 
    public View getView(int position, View view, ViewGroup parent) { 
     LayoutInflater inflater = context.getLayoutInflater(); 
     View rowView= inflater.inflate(R.layout.list_single, null, true); 

     TextView txtTitle = (TextView) rowView.findViewById(R.id.txt); 
     ImageView imageView = (ImageView) rowView.findViewById(R.id.img); 

     txtTitle.setText(mItems.get(position)); 

     if(items.get(position).endsWith(".docx")) { 
      imageView.setImageBitmap(docIcons.get("docx")) 

     } // and so on for other types... 
    } 
} 

這個例子不包括你如何獲得你的圖標。您可以從互聯網上下載它們,將它們存儲在磁盤上,當應用程序需要這些圖標時 - 您可以將它們從磁盤加載爲位圖,並將每個位圖存儲在內存中一次,然後在視圖中重新使用它們。與RecyclerView一起實現這個邏輯,您將獲得相當高效的應用程序,不浪費內存並且響應速度非常快。

你不必存儲HashMap在適配器的位圖,但它是,如果你只在一個地方使用它不錯的選擇。如果你需要在不同的活動中使用它,然後再考慮保持這個HashMap別的地方,它不會被利用類似於ListViews不同活動之間的每一次用戶交換機重新加載。

處理與相同的圖像

多個活動關於這取決於你如何存儲圖像的活動。如果它們也從互聯網下載並緩存在磁盤上,則可以按照本答案的ListView部分所述執行相同操作。只需保留已加載到內存中的圖像列表並使用

imageView.setImageBitmap(someBitmap) 

當您需要將其顯示在活動的特定部分時。

在你的應用程序的資源正在運行的情況是,更容易,因爲你可以做這樣的事情:

Drawable dr = context.resources.getDrawable(R.drawable.my_favourite_image); 
imageView.setImageDrawable(dr); 

內存高效地使用所有的工作都在抽油煙機下在這裏完成。

如何避免下載相同的圖像,但使用緩存一個

這取決於你如何去跟蹤每個圖像的獨特性。例如。如果每個圖像具有唯一的URL,最基本的解決方案是使用HashMap和圖像的URL作爲關鍵字。

更復雜,但更靈活,更正確的決定是使用類似Guava緩存工具。這不是針對Android的具體問題,而是非常廣泛的主題,但您可以在take a look here

雖然如果您計劃混淆圖像的複雜佈局並關心性能,請檢查Ankothis benchmark。這與內容緩存無關,但佈局渲染性能可以提高3倍甚至更多。

+0

感謝克勞斯,但你能不能把服用看看我添加更新部分。我只想澄清我的意思。非常感謝 – pixel

+1

@pixel我更新了答案。正如我曾經說過的,緩存邏輯很大程度上取決於您需要哪些選項來識別獨特的緩存部分以及如何讓緩存保持最新狀態。這是關鍵。沒有這些信息,很難做出最佳決策。 –

+0

謝謝克勞斯,我想我現在明白了,謝謝你的偉大解釋。就我而言,唯一性可以通過在這種情況下擴展文檔(即docx,.pdf,.txt,.js,...)來確定,並且緩存永遠不會過期,因爲文檔不會改變我猜的類型。另外,我不會先下載圖像並將它們保存到磁盤,然後將它們加載到列表中。我準備好接受你的回答,只要告訴我你是否必須根據此評論添加內容。非常感激。 – pixel