轉:緩存
一、 爲何要異步加載圖片網絡
下載圖片比較費時,先顯示文字部分,讓加載圖片的過程在後臺,以提高用戶體驗異步
二、 SoftReference的做用ide
棧內存—引用spa
堆內存—對象線程
Eg:code
Object obj = new Object();對象
Obj = null;blog
當垃圾收集器啓動時,會回收對象;圖片
當一個對象沒有任何引用指向,就會被回收。
SoftReference<Object>sr = new SoftReference<Object>(new Obnject());
引用是軟引用,當垃圾回收器啓動時,系統會判斷內存是否充足,內存不足時,即便對象有引用指向,也會被回收。
Object obj = sr.get();獲取軟引用指向的對象,當已被回收時,返回NULL。
在這裏咱們使用SoftReference對象來創建圖片緩存
三、 異步加載圖片的方法
基本流程:
A、 獲取圖片URL
B、 根據URL查詢緩存
Eg:假如取回了20條微博,其中5條微博是同一我的發的,這樣這我的的頭像就要被取回5次,這是不合理的。
解決方法:把從網絡上下載的圖片以鍵值對的方式放到緩存裏,鍵是URL,值是下載的圖片,下次再去讀取圖片時,先看URL是否在緩存裏,若是在,就不用下載了。
C、 訪問緩存or訪問網絡
D、 獲得圖片對象
E、 顯示圖片
代碼示例:
/** * 實現圖片的異步加載 * @author Zhu * */ public class AsyncImageLoader { //圖片緩存對象,鍵是URL,值是SoftReference對象,該對象指向一個Drawable對象 private Map<String,SoftReference<Drawable>> imageCache = new HashMap<String,SoftReference<Drawable>>(); /** * 實現圖片的異步加載 * @param imageUrl * @return */ public Drawable loadDrawable(final String imageUrl){ //查詢緩存,查看當前要下載的圖片是否已經在緩存中 if(imageCache.containsKey(imageUrl)){ SoftReference<Drawable> softReference = imageCache.get(imageUrl); if(softReference.get()!=null){ return softReference.get();//還沒被回收 } } final Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub super.handleMessage(msg); //Handler是與主程序處於同一線程的,在這裏能夠寫加載完圖片的處理,顯示or存儲or... } }; //新開闢一個線程 new Thread(){ @Override public void run() { // TODO Auto-generated method stub super.run(); Drawable drawable = loadImageFromUrl(imageUrl); imageCache.put(imageUrl,new SoftReference<Drawable>(drawable)); Message message = handler.obtainMessage(0,drawable); handler.sendMessage(message); } }.start(); return null; } /** * 根據圖片的URL從網絡上下載圖片 * @param imageUrl * @return */ public Drawable loadImageFromUrl(String imageUrl){ try{ //根據圖片的URL,下載圖片,並生成一個Drawable對象 return Drawable.createFromStream(new URL(imageUrl).openStream(), "src"); //另外一種下載圖片的方法: // Drawable icon; // HttpURLConnection hc=(HttpURLConnection)new URL(imageUrl).openConnection(); // icon=new Drawable(hc.getInputStream()); // hc.disconnect(); }catch (Exception e) { // TODO: handle exception throw new RuntimeException(e); } } }