Kotlin 開發第 21 天 LayoutSwitch (RecyclerView + GridLayoutManager + Out of memory)

在 iOS 中,我們通過 UICollectionView 可以靈活的進行排版,這次打算通過 GridLayout 搭配按鈕來進行排版的切換。

Components

  • RecyclerView
  • GridLayoutManager

Layout Switch

這次除了將內容切成 MVC 另外還自訂了一個 Menu (Toolbar)

在 Toolbar 上面放置一個切換用的按鈕(右邊)讓 Activity 去處理切換 Layout 的功能。


Menu

建立檔案 /res/menu/menu_main.xml 為 Menu 提供一個按鈕用來切換 Layout

在 MainActivity 中實現 Switch 功能

Switch 功能實現


Layout

準備好兩種佈局方案來進行切換,這兩個 Layout 都設定寬度為 match_parent 之後再使用的時候再給不同的寬達成我們要的效果。

res/layout/layout_item_big(左邊) / res/layout/layout_item_small(右邊)

 


Model


Adapter

我們自己定義了兩種 View Type

通過 override getItemViewType() 來重新定義 viewType 對應的 Int

onCreateViewHolder 中,根據 View Type 指定 Layout 文件

class ViewHolder 中,根據 View  Type 綁定對應的 Layout 元件,並賦予值。

其實在這裡,一開始因為引入的圖片比較大,一下子就出現了 Out of memory 的警告,後來查可以通過 BitmapFacotry 來解決。

但因為一天研究一個內容的時間有限,我這裡先直接將 1024 x 768 的圖片替換成 512 x 384 的小圖,文章後面會提到 memory 計算的內容。


OOM(Out Of Memory)

在寫這個應用的時候遇到了一件事情,我準備了 20 張大小差不多是 100kb 左右的圖片,長寬大概是 1024 x 800

結果打開 App 以後非常快的就碰到了記憶體不足的問題

而當我換成一系列 50kb 左右的圖片,長寬約為 512 x 400 的圖片時,
明明兩種圖片都很小,只是解析度變了就沒有出現過 OOM了。

後來專門查了一下才發現,原來加載圖片所佔用的 Memory 和檔案的大小是不一致的


Bitmap

圖片在電腦上是以位圖(bitmap)的形式存在的,而位圖是一個矩形點陣,每一個點我們稱為像素也就是 pixel.
一張 MxN 大小的圖,是由 MxN 個明、暗度像素所組成的。

而每一個像素根據明暗度的不同用灰度值 (Gray Level) 來表示,將白色的灰度值定為 255、黑色定為 0.

而彩色圖片是由 R G B 三個單色圖像組成。


色彩的存儲方式

A 代表 Alpha(透明度) RGB 分別是 Red Green Blue

  • ARGB_4444 – ARGB 分別佔用 4位,合起來就是 16位,也就是 2 字節。
  • ARGB_8888 – ARGB 分別佔用 8位,合起來就是 32位,也就是 4 字節。
  • ALPHA_8 – 只有 A 佔用了4位,僅表示透明度而沒有色彩,佔用 1 字節。
  • RGB_565 – RGB 分別佔用 5 6 5 位,不表示透明度,共佔用 16 位,佔用 4 字節。

佔用的位數越多意味著可以存儲的色彩越豐富,但佔用的記憶體同樣也更多。


計算一張圖片佔用的 Memory

假設我們用的其中一張圖片為 1024 x 768 pixel 格式為 ARGB_8888

那麼每一個像素佔用的是 8 + 8 + 8 + 8 = 32 位 = 4 字節
而一張圖片佔用的 memory 就是 1024 * 768 * 4 / 1024 = 3072 KB = 3MB.

所以當我加載 20 張圖片的時候,直接就佔用了 60MB 的記憶體。


設備給 App 分配的 Memory

通過 ActivityManager 我們可以知道設備給 App 分配了多少 Memory 來使用,單位是 MB.

但實際上在 allocate memory 給圖片的時候,似乎看的不是上面所給的 memory

還有另外一種 Memory 查詢功能,不過看從數字來看是設備的 Memory


筆記

  • 研究: 了解緩存方案 LruCache
  • 研究: 了解 Memory 機制
  • TODO: 嘗試通過 Glide 來處理圖片

參考

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *