您好,登錄后才能下訂單哦!
學(xué)習(xí)谷歌文檔,總結(jié)如下:
1.圖片加載框架的封裝
1)利用HttpURLConnection來(lái)封裝網(wǎng)絡(luò)加載圖片的方法
2)創(chuàng)建自定義的AsyncTask來(lái)封裝1)中加載網(wǎng)絡(luò)圖片的方法,并顯示到控件上。
3)暴露方法封裝2)中自定義的加載并顯示圖片的AsyncTask
走完上面這幾步,只需調(diào)用一個(gè)方法,就可以從網(wǎng)絡(luò)上加載一張圖片并且顯示到控件上了。
解決List并發(fā)下載圖片錯(cuò)位的問(wèn)題
但是,谷歌文檔中說(shuō)上面代碼會(huì)存在一個(gè)問(wèn)題。就是如果在List里使用,復(fù)用的話,可能會(huì)發(fā)生圖
圖片錯(cuò)位的問(wèn)題:就是某個(gè)item顯示的圖片,可能顯示的圖片是之前的item的圖片。因?yàn)橹暗倪@
張圖片可能加載時(shí)間比較長(zhǎng),滑動(dòng)后p_w_picpathview是復(fù)用的,所以后面的item可能會(huì)顯示之前的item的
圖片。
這種就是由于并發(fā)產(chǎn)生的問(wèn)題,谷歌工程師是這么解決問(wèn)題的:
1》定義一個(gè)類 class DownloadedDrawable extends ColorDrawable,然后將下載的異步任務(wù)
DownloadAsyncTask與其綁定起來(lái)。
public static void display(Context context,String url, ImageView p_w_picpathView) { Bitmap bitmapFromMemCache = LruCacheUtil.getBitmapFromMemCache(url); if(bitmapFromMemCache != null){ p_w_picpathView.setImageBitmap(bitmapFromMemCache); }else{ if (cancelPotentialDownload(url, p_w_picpathView)) { BitmapDownloaderTask task = new BitmapDownloaderTask(context,p_w_picpathView); DownloadedDrawable downloadedDrawable = new DownloadedDrawable(task); p_w_picpathView.setImageDrawable(downloadedDrawable); task.execute(url); } } }
2》定義2個(gè)方法
BitmapDownloaderTask getBitmapDownloaderTask(ImageView p_w_picpathView)
--得到與ImageView綁定的異步下載任務(wù)
public static BitmapDownloaderTask getBitmapDownloaderTask(ImageView p_w_picpathView) { if (p_w_picpathView != null) { Drawable drawable = p_w_picpathView.getDrawable(); if (drawable instanceof DownloadedDrawable) { DownloadedDrawable downloadedDrawable = (DownloadedDrawable)drawable; return downloadedDrawable.getBitmapDownloaderTask(); } } return null; }
boolean cancelPotentialDownload(String url, ImageView p_w_picpathView)
--取消可能正在進(jìn)行的下載,并返回是否已經(jīng)取消。
如果與p_w_picpathView綁定的下載任務(wù)不為空,再判斷與ImageView綁定的異步下載任務(wù)的URL,如果
為null或者是與當(dāng)前方法傳遞進(jìn)來(lái)URL不一致,說(shuō)明異步下載任務(wù)正在執(zhí)行之前的下載,就取消任
務(wù),否則說(shuō)明任務(wù)正在執(zhí)行中且url一致,就不重新開啟任務(wù)。
private static boolean cancelPotentialDownload(String url, ImageView p_w_picpathView) { BitmapDownloaderTask bitmapDownloaderTask = BitmapDownloaderTask.getBitmapDownloaderTask(p_w_picpathView); if (bitmapDownloaderTask != null) { String bitmapUrl = bitmapDownloaderTask.url; if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) { bitmapDownloaderTask.cancel(true); } else { // The same URL is already being downloaded. return false; } } return true; }
解決圖片緩存的問(wèn)題
1》用內(nèi)存來(lái)緩存,使用LruCache這個(gè)類。
內(nèi)存的特點(diǎn):
內(nèi)存加載速度比較快,但是內(nèi)存在開關(guān)機(jī)之后會(huì)被回收,緩存的數(shù)據(jù)會(huì)消失。
底層:
LinkedHashMap來(lái)實(shí)現(xiàn)存儲(chǔ)
實(shí)現(xiàn)原理:
當(dāng)從url下載圖片之前,先判斷緩存中存不存在圖片,如果存在直接加載圖片,不存在則
去網(wǎng)絡(luò)請(qǐng)求圖片。
當(dāng)AsyncTask下載完圖片之后,如果不為null,就存放到緩存中。
于是我寫了個(gè)工具類LruCacheUtils來(lái)完成圖片的緩存
public class LruCacheUtil { //LruCache for bitmap private static LruCache<String, Bitmap> mMemoryCache; static { // Get max available VM memory, exceeding this amount will throw an // OutOfMemory exception. Stored in kilobytes as LruCache takes an // int in its constructor. final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); // Use 1/8th of the available memory for this memory cache. final int cacheSize = maxMemory / 8; mMemoryCache = new LruCache<String, Bitmap>(cacheSize) { @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) @Override protected int sizeOf(String key, Bitmap bitmap) { // The cache size will be measured in kilobytes rather than // number of items. return bitmap.getByteCount() / 1024; } }; } public static void addBitmapToMemoryCache(String key, Bitmap bitmap) { if (getBitmapFromMemCache(key) == null) { mMemoryCache.put(key, bitmap); } } public static Bitmap getBitmapFromMemCache(String key) { return mMemoryCache.get(key); } }
2》使用磁盤(Disk)來(lái)緩存,使用DiskLruCache(這個(gè)類google文檔里并沒有提供)
Android DiskLruCache 源碼解析 硬盤緩存的絕佳方案
http://blog.csdn.net/lmj623565791/article/details/47251585
下載鏈接
http://http://www.oschina.net/p/disklrucache
Android本地緩存DiskLruCache完整詳細(xì)學(xué)習(xí)示例
http://www.2cto.com/kf/201501/368172.html
雖然利用內(nèi)存來(lái)緩存,加載圖片的時(shí)候速度比較快,但是像GridView會(huì)很快地占滿內(nèi)存。當(dāng)應(yīng)
用非正常關(guān)閉(如被電話應(yīng)用打斷、運(yùn)行在后臺(tái)的時(shí)候被殺死)會(huì)導(dǎo)致cache被銷毀清空。
注意:獲取圖片應(yīng)該在后臺(tái)進(jìn)行
Of course, fetching p_w_picpaths from disk is slower than loading from memory and should be done in a
background thread, as disk read times can be unpredictable.(from google doc)
緩存位置:
有外部存儲(chǔ)設(shè)備就存放到外部存儲(chǔ)設(shè)備中,否則存放到應(yīng)用包名目錄下。
2.布局優(yōu)化
sdk下的一些工具并不是專門針對(duì)Eclipse的,Android Studio也可以使用。
sdk/tools下的工具Hierarchy Viewer
http://wear.techbrood.com/training/improving-layouts/optimizing-layout.html#Inspect
爽處1:可以查看布局結(jié)構(gòu)某個(gè)節(jié)點(diǎn)的3個(gè)方法Measure、Layout、Draw執(zhí)行所需要的時(shí)間,這樣
如果某個(gè)item的加載時(shí)間比較長(zhǎng),你就應(yīng)該要優(yōu)化了。
使用這個(gè)工具可能會(huì)遇到的問(wèn)題:
問(wèn)題:使用Hierarchyviewer,measure、layout、draw時(shí)間未顯示?
解決辦法:點(diǎn)擊菜單 Profile Node,重新加載之后就有了
免責(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)容。