日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

android 下的网络图片加载

發布時間:2025/7/14 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android 下的网络图片加载 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2019獨角獸企業重金招聘Python工程師標準>>>

Android圖片的異步加載,主要原理:

加載圖片時先查看緩存中時候存在該圖片,如果存在則返回該圖片,否則先加載載一個默認的占位圖片,同時創建一個通過網絡獲取圖片的任務并添加,任務完成后放松消息給主線程更新界面。

廢話少說,先貼上代碼:


package com.wangge.uumao.http; ?
?
import java.lang.ref.SoftReference; ?
import java.util.ArrayList; ?
import java.util.HashMap; ?
import java.util.List; ?
import java.util.Map; ?
?
import android.graphics.Bitmap; ?
import android.os.Handler; ?
import android.os.Message; ?
import android.util.Log; ?
import android.widget.ImageView; ?
?
import com.wangge.uumao.util.PicUtil; ?
?
public class AsynImageLoader { ?
??? private static final String TAG = "AsynImageLoader"; ?
??? // 緩存下載過的圖片的Map? ?
??? private Map<String, SoftReference<Bitmap>> caches; ?
??? // 任務隊列? ?
??? private List<Task> taskQueue; ?
??? private boolean isRunning = false; ?
???? ?
??? public AsynImageLoader(){ ?
??????? // 初始化變量? ?
??????? caches = new HashMap<String, SoftReference<Bitmap>>(); ?
??????? taskQueue = new ArrayList<AsynImageLoader.Task>(); ?
??????? // 啟動圖片下載線程? ?
??????? isRunning = true; ?
??????? new Thread(runnable).start(); ?
??? } ?
???? ?
??? /**
???? * ?
???? * @param imageView 需要延遲加載圖片的對象
???? * @param url 圖片的URL地址
???? * @param resId 圖片加載過程中顯示的圖片資源
???? */ ?
??? public void showImageAsyn(ImageView imageView, String url, int resId){ ?
??????? imageView.setTag(url); ?
??????? Bitmap bitmap = loadImageAsyn(url, getImageCallback(imageView, resId)); ?
???????? ?
??????? if(bitmap == null){ ?
??????????? imageView.setImageResource(resId); ?
??????? }else{ ?
??????????? imageView.setImageBitmap(bitmap); ?
??????? } ?
??? } ?
???? ?
??? public Bitmap loadImageAsyn(String path, ImageCallback callback){ ?
??????? // 判斷緩存中是否已經存在該圖片? ?
??????? if(caches.containsKey(path)){ ?
??????????? // 取出軟引用? ?
??????????? SoftReference<Bitmap> rf = caches.get(path); ?
??????????? // 通過軟引用,獲取圖片? ?
??????????? Bitmap bitmap = rf.get(); ?
??????????? // 如果該圖片已經被釋放,則將該path對應的鍵從Map中移除掉? ?
??????????? if(bitmap == null){ ?
??????????????? caches.remove(path); ?
??????????? }else{ ?
??????????????? // 如果圖片未被釋放,直接返回該圖片? ?
??????????????? Log.i(TAG, "return image in cache" + path); ?
??????????????? return bitmap; ?
??????????? } ?
??????? }else{ ?
??????????? // 如果緩存中不常在該圖片,則創建圖片下載任務? ?
??????????? Task task = new Task(); ?
??????????? task.path = path; ?
??????????? task.callback = callback; ?
??????????? Log.i(TAG, "new Task ," + path); ?
??????????? if(!taskQueue.contains(task)){ ?
??????????????? taskQueue.add(task); ?
??????????????? // 喚醒任務下載隊列? ?
??????????????? synchronized (runnable) { ?
??????????????????? runnable.notify(); ?
??????????????? } ?
??????????? } ?
??????? } ?
???????? ?
??????? // 緩存中沒有圖片則返回null? ?
??????? return null; ?
??? } ?
???? ?
??? /**
???? * ?
???? * @param imageView ?
???? * @param resId 圖片加載完成前顯示的圖片資源ID
???? * @return
???? */ ?
??? private ImageCallback getImageCallback(final ImageView imageView, final int resId){ ?
??????? return new ImageCallback() { ?
???????????? ?
??????????? @Override ?
??????????? public void loadImage(String path, Bitmap bitmap) { ?
??????????????? if(path.equals(imageView.getTag().toString())){ ?
??????????????????? imageView.setImageBitmap(bitmap); ?
??????????????? }else{ ?
??????????????????? imageView.setImageResource(resId); ?
??????????????? } ?
??????????? } ?
??????? }; ?
??? } ?
???? ?
??? private Handler handler = new Handler(){ ?
?
??????? @Override ?
??????? public void handleMessage(Message msg) { ?
??????????? // 子線程中返回的下載完成的任務? ?
??????????? Task task = (Task)msg.obj; ?
??????????? // 調用callback對象的loadImage方法,并將圖片路徑和圖片回傳給adapter? ?
??????????? task.callback.loadImage(task.path, task.bitmap); ?
??????? } ?
???????? ?
??? }; ?
???? ?
??? private Runnable runnable = new Runnable() { ?
???????? ?
??????? @Override ?
??????? public void run() { ?
??????????? while(isRunning){ ?
??????????????? // 當隊列中還有未處理的任務時,執行下載任務? ?
??????????????? while(taskQueue.size() > 0){ ?
??????????????????? // 獲取第一個任務,并將之從任務隊列中刪除? ?
??????????????????? Task task = taskQueue.remove(0); ?
??????????????????? // 將下載的圖片添加到緩存? ?
??????????????????? task.bitmap = PicUtil.getbitmap(task.path); ?
??????????????????? caches.put(task.path, new SoftReference<Bitmap>(task.bitmap)); ?
??????????????????? if(handler != null){ ?
??????????????????????? // 創建消息對象,并將完成的任務添加到消息對象中? ?
??????????????????????? Message msg = handler.obtainMessage(); ?
??????????????????????? msg.obj = task; ?
??????????????????????? // 發送消息回主線程? ?
??????????????????????? handler.sendMessage(msg); ?
??????????????????? } ?
??????????????? } ?
???????????????? ?
??????????????? //如果隊列為空,則令線程等待? ?
??????????????? synchronized (this) { ?
??????????????????? try { ?
??????????????????????? this.wait(); ?
??????????????????? } catch (InterruptedException e) { ?
??????????????????????? e.printStackTrace(); ?
??????????????????? } ?
??????????????? } ?
??????????? } ?
??????? } ?
??? }; ?
???? ?
??? //回調接口? ?
??? public interface ImageCallback{ ?
??????? void loadImage(String path, Bitmap bitmap); ?
??? } ?
???? ?
??? class Task{ ?
??????? // 下載任務的下載路徑? ?
??????? String path; ?
??????? // 下載的圖片? ?
??????? Bitmap bitmap; ?
??????? // 回調對象? ?
??????? ImageCallback callback; ?
???????? ?
??????? @Override ?
??????? public boolean equals(Object o) { ?
??????????? Task task = (Task)o; ?
??????????? return task.path.equals(path); ?
??????? } ?
??? } ?
}

源代碼的17-24行是一些變量,數組的聲明。

private static final String TAG = "AsynImageLoader"; ?
??? // 緩存下載過的圖片的Map? ?
??? private Map<String, SoftReference<Bitmap>> caches; ?
??? // 任務隊列? ?
??? private List<Task> taskQueue; ?
??? private boolean isRunning = false;

值得一提的是的這里的下載過的圖片的mAp是軟應用了,為什么了。我們查閱資料以后得知:
如果一個對象只具有軟引用,那就類似于可有可物的 生活用品。如果內存空間足夠,垃圾回收器就不會回收它,如果內存空間不足了,就會回收這些對象的內存。只 要垃圾回收器沒有回收它,該對象就可以被程序使用。軟引用可用來實現內存敏感的高速緩存。?軟引用可以和一個引用隊列(ReferenceQueue)聯 合使用,如果軟引用所引用的對象被垃圾回收,Java虛擬機就會把這個軟引用加入到與之關聯的引用隊列中。

?由于圖片是大對象了,確保沒有足夠的緩存以后,java虛擬機能夠將其回收。

代碼的25-33行做了一件事,來初始化變量。

public AsynImageLoader(){ ?
??????? // 初始化變量? ?
??????? caches = new HashMap<String, SoftReference<Bitmap>>(); ?
??????? taskQueue = new ArrayList<AsynImageLoader.Task>(); ?
??????? // 啟動圖片下載線程? ?
??????? isRunning = true; ?
??????? new Thread(runnable).start(); ?
??? }

并且啟動圖片下載線程。
40行-50行主要是用來啟動異步線程來展示圖片。

public void showImageAsyn(ImageView imageView, String url, int resId){ ?
??????? imageView.setTag(url); ?
??????? Bitmap bitmap = loadImageAsyn(url, getImageCallback(imageView, resId)); ?
???????? ?
??????? if(bitmap == null){ ?
??????????? imageView.setImageResource(resId); ?
??????? }else{ ?
??????????? imageView.setImageBitmap(bitmap); ?
??????? } ?
??? }

這個方法,主要調用了本段源代碼,最核心的方法loadImageAsyn方法。

public Bitmap loadImageAsyn(String path, ImageCallback callback){ ?
??????? // 判斷緩存中是否已經存在該圖片? ?
??????? if(caches.containsKey(path)){ ?
??????????? // 取出軟引用? ?
??????????? SoftReference<Bitmap> rf = caches.get(path); ?
??????????? // 通過軟引用,獲取圖片? ?
??????????? Bitmap bitmap = rf.get(); ?
??????????? // 如果該圖片已經被釋放,則將該path對應的鍵從Map中移除掉? ?
??????????? if(bitmap == null){ ?
??????????????? caches.remove(path); ?
??????????? }else{ ?
??????????????? // 如果圖片未被釋放,直接返回該圖片? ?
??????????????? Log.i(TAG, "return image in cache" + path); ?
??????????????? return bitmap; ?
??????????? } ?
??????? }else{ ?
??????????? // 如果緩存中不常在該圖片,則創建圖片下載任務? ?
??????????? Task task = new Task(); ?
??????????? task.path = path; ?
??????????? task.callback = callback; ?
??????????? Log.i(TAG, "new Task ," + path); ?
??????????? if(!taskQueue.contains(task)){ ?
??????????????? taskQueue.add(task); ?
??????????????? // 喚醒任務下載隊列? ?
??????????????? synchronized (runnable) { ?
??????????????????? runnable.notify(); ?
??????????????? } ?
??????????? } ?
??????? } ?
???????? ?
??????? // 緩存中沒有圖片則返回null? ?
??????? return null; ?
??? }

首先判斷緩存池中是否包含了這個圖片,如果有這個圖片,就從緩存中取得這個圖片,否則的話,就從網絡段來請求。這就是本方法的作用。

而runnable是從網絡直接下載圖片的方法。

private Runnable runnable = new Runnable() { ?
118.???????? ?
119.??????? @Override ?
120.??????? public void run() { ?
121.??????????? while(isRunning){ ?
122.??????????????? // 當隊列中還有未處理的任務時,執行下載任務? ?
123.??????????????? while(taskQueue.size() > 0){ ?
124.??????????????????? // 獲取第一個任務,并將之從任務隊列中刪除? ?
125.??????????????????? Task task = taskQueue.remove(0); ?
126.??????????????????? // 將下載的圖片添加到緩存? ?
127.??????????????????? task.bitmap = PicUtil.getbitmap(task.path); ?
128.??????????????????? caches.put(task.path, new SoftReference<Bitmap>(task.bitmap)); ?
129.??????????????????? if(handler != null){ ?
130.??????????????????????? // 創建消息對象,并將完成的任務添加到消息對象中? ?
131.??????????????????????? Message msg = handler.obtainMessage(); ?
132.??????????????????????? msg.obj = task; ?
133.??????????????????????? // 發送消息回主線程? ?
134.??????????????????????? handler.sendMessage(msg); ?
135.??????????????????? } ?
136.??????????????? } ?
137.???????????????? ?
138.??????????????? //如果隊列為空,則令線程等待? ?
139.??????????????? synchronized (this) { ?
140.??????????????????? try { ?
141.??????????????????????? this.wait(); ?
142.??????????????????? } catch (InterruptedException e) { ?
143.??????????????????????? e.printStackTrace(); ?
144.??????????????????? } ?
145.??????????????? } ?
146.??????????? } ?
147.??????? } ?
148.??? };

上述的代碼告訴我們這樣一個意思,通過一個消息的隊列來下載圖片,如果沒有此線程的話,就令線程等待。

這就實現了android異步加載圖片的應用。

轉載于:https://my.oschina.net/u/1182603/blog/174153

總結

以上是生活随笔為你收集整理的android 下的网络图片加载的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。