載入本地圖片模糊,Glide載入網路圖片卻很清晰

yiersa發表於2018-04-01

問題

前幾天做專案,同事遇到個問題,載入drawable中圖片很模糊,用Glide載入就清晰,其中圖片放在xhdpi資料夾中,螢幕解析度是1280x720,奇怪的是xhdpi的圖片對應的就是1280x720的解析度,為什麼會不清晰呢?我後來寫了個demo驗證了下,發現確實會不清晰,如下:

載入本地drawable不清晰

不清晰
最後一個glide載入清晰
清晰
首先是想起以前看過的文章Android 開發繞不過的坑:你的 Bitmap 究竟佔多大記憶體?Android應用效能優化系列檢視篇——隱藏在資源圖片中的記憶體殺手看完這兩篇文章應該就能理解為什麼圖片會模糊,簡單說就是像放在drawable-mdpi、hdpi、xhdpi、xxhdpi中的圖片分別是對應不同解析度螢幕的,假如我只在xxhdpi放一張圖片,在較低解析度的螢幕上會壓縮,如果在mdpi中放一張圖片,在高解析度螢幕上就會放大,計算公式如下:

資源圖片最終大小 = 寬 x(裝置密度 / 資源維度密度)x 高(裝置密度 / 資源維度密度) x 4

裝置密度是說不同解析度的螢幕對應的密度,資源維度密度是說drawable-mdpi、hdpi、xhdpi、xxhdpi這些分別也對應不同的密度,具體見下表

資料夾 資源維度密度 對應解析度 裝置密度
drawable-mdpi 160 320x480 160
drawable-hdpi 240 480x800 240
drawable-xhdpi 320 720x1280 320
drawable-xxhdpi 480 1080x1920 480
drawable-xxxdpi 640 1440*2560 560

其中資源維度密度是系統規定好的,因為螢幕解析度和螢幕尺寸不同,裝置密度這個值可以用 getResources().getDisplayMetrics().densityDpi檢視,我測試的電視列印出來的裝置密度是240,很奇怪的不是320,後來在這篇文章android 手機螢幕密度等級和螢幕邏輯尺寸才知道這個值是廠商定義的,所以同解析度不同螢幕尺寸的裝置密度會有不同,開始時並不知道這一點,只是認為放在xhdpi資料夾中就應該是對應的1280x720解析度的螢幕,就不應該會被壓縮。

解答

回到我們剛才的問題,圖片尺寸是411x195,使用本地圖片和glide載入記憶體佔用分別是179871和320580

記憶體佔用
根據公式: 資源圖片最終大小 = 寬 x(裝置密度 / 資源維度密度)x 高(裝置密度 / 資源維度密度) x 4

用glide載入可以不被壓縮,所以記憶體佔用=411x195x4=320580,和列印值相等。計算本地載入時寬=411x240/320=308.25取整308,高195x240/320=146.25取整146,308x146x4=179872,和列印出來的相等。到這問題也算是解決了,開始是因為不知道螢幕密度是由廠商規定的,並不是由螢幕解析度規定的,所以就算把圖片放到的解析度對應的drawable中還是有可能會被壓縮。

總結

我們Android裡面的長度單位推薦用dp,表示和裝置無關的一個單位,用來在不同解析度上看起來效果一樣,或者說在相同解析度不同螢幕尺寸下看起來效果不一致。dp以160為1,表示在160密度的螢幕上1dp表示1px,那麼在320的螢幕上1dp表示2px,在640的螢幕上1dp表示4px,以此類推。 假定有兩塊5寸螢幕,一塊1280x720解析度,一塊1920x1080,現在上面放一個80dpx80dp的圖片,這個圖片在1280的螢幕上最終顯示160pxx160px,在1920上顯示240pxx240px, 這樣160/720=0.222,240/1080=0.222,這樣圖片在螢幕所佔比例一樣,即在低解析度上能放幾個按鈕,在高解析度上也是放幾個按鈕,位置大小看起來都一樣。

但是一般的同解析度下電視螢幕都要比手機螢幕大,手機一排放兩個按鈕可能就差不多了,但是電視上如果只放兩個按鈕就會顯得按鈕很大,很不協調,電視可能能放下四個甚至更多按鈕,這相當於是螢幕越大應該顯示的東西越多。所以這才有了廠商自定義的裝置密度,比如同樣1920x1080解析度,手機的裝置密度是480,電視的裝置密度可能只有240(我測試的一款電視只有213),根據公式:

資源圖片最終大小 = 寬 x(裝置密度 / 資源維度密度)x 高(裝置密度 / 資源維度密度) x 4 100dpx20dp的按鈕在手機上實際300pxX60px,但在電視上只有150pxX30px,在1080手機上一排最多隻能放3個了,但在電視上就可以1080/150=7個(先不考慮電視的橫豎屏), 當然實際不可能會放7個這麼多。手機上一個寬度佔螢幕寬度三分之一的按鈕看起來效果是比較好的,但是如果佔了電視螢幕寬度三分之一看起來就不那麼優雅了。

思考

上面討論的是手機和電視這樣相比螢幕尺寸差別很大的,但是隻針對電視,不同廠商不同尺寸電視(40寸,55寸,65寸這樣的尺寸),裝置密度差別也很大,比如我測試的兩個電視都是1280x720的,但是一個密度是213,一個是240,但是具體螢幕尺寸都是一樣的21寸,如果我們繼續使用dp,sp這樣的單位根據上面的公式可知:實際寬=寬x裝置密度/資源維度密度,導致寬高在裝置密度為213的上面的會比240上面的小,所以最終採用的是px單位,以1280x720為標準,在不同解析度螢幕上計算實際的畫素值,比如以1280x720為模板設計的圖片尺寸是100x100,那麼在1920x1080上面就是150x150大小,這樣就能比較完美適應不同螢幕了

相關文章