安卓图片异步加载
Android图片的异步加载,主要原理:
加载图片时先查看缓存中时候存在该图片,如果存在则返回该图片,否则先加载载一个默认的占位图片,同时创建一个通过网络获取图片的任务并添加,任务完成后放松消息给主线程更新界面。
使用方法:
01.AsynImageLoader asynImageLoader = new AsynImageLoader();
02.asynImageLoader.showImageAsyn(imageView, imageUrl, resId);
类代码:
01.package com.wangge.uumao.http; 02. 03.import java.lang.ref.SoftReference; 04.import java.util.ArrayList; 05.import java.util.HashMap; 06.import java.util.List; 07.import java.util.Map; 08. 09.import android.graphics.Bitmap; 10.import android.os.Handler; 11.import android.os.Message; 12.import android.util.Log; 13.import android.widget.ImageView; 14. 15.import com.wangge.uumao.util.PicUtil; 16. 17.public class AsynImageLoader { 18. private static final String TAG = "AsynImageLoader"; 19. // 缓存下载过的图片的Map 20. private Map<String, SoftReference<Bitmap>> caches; 21. // 任务队列 22. private List<Task> taskQueue; 23. private boolean isRunning = false; 24. 25. public AsynImageLoader(){ 26. // 初始化变量 27. caches = new HashMap<String, SoftReference<Bitmap>>(); 28. taskQueue = new ArrayList<AsynImageLoader.Task>(); 29. // 启动图片下载线程 30. isRunning = true; 31. new Thread(runnable).start(); 32. } 33. 34. /** 35. * 36. * @param imageView 需要延迟加载图片的对象 37. * @param url 图片的URL地址 38. * @param resId 图片加载过程中显示的图片资源 39. */ 40. public void showImageAsyn(ImageView imageView, String url, int resId){ 41. imageView.setTag(url); 42. Bitmap bitmap = loadImageAsyn(url, getImageCallback(imageView, resId)); 43. 44. if(bitmap == null){ 45. imageView.setImageResource(resId); 46. }else{ 47. imageView.setImageBitmap(bitmap); 48. } 49. } 50. 51. public Bitmap loadImageAsyn(String path, ImageCallback callback){ 52. // 判断缓存中是否已经存在该图片 53. if(caches.containsKey(path)){ 54. // 取出软引用 55. SoftReference<Bitmap> rf = caches.get(path); 56. // 通过软引用,获取图片 57. Bitmap bitmap = rf.get(); 58. // 如果该图片已经被释放,则将该path对应的键从Map中移除掉 59. if(bitmap == null){ 60. caches.remove(path); 61. }else{ 62. // 如果图片未被释放,直接返回该图片 63. Log.i(TAG, "return image in cache" + path); 64. return bitmap; 65. } 66. }else{ 67. // 如果缓存中不常在该图片,则创建图片下载任务 68. Task task = new Task(); 69. task.path = path; 70. task.callback = callback; 71. Log.i(TAG, "new Task ," + path); 72. if(!taskQueue.contains(task)){ 73. taskQueue.add(task); 74. // 唤醒任务下载队列 75. synchronized (runnable) { 76. runnable.notify(); 77. } 78. } 79. } 80. 81. // 缓存中没有图片则返回null 82. return null; 83. } 84. 85. /** 86. * 87. * @param imageView 88. * @param resId 图片加载完成前显示的图片资源ID 89. * @return 90. */ 91. private ImageCallback getImageCallback(final ImageView imageView, final int resId){ 92. return new ImageCallback() { 93. 94. @Override 95. public void loadImage(String path, Bitmap bitmap) { 96. if(path.equals(imageView.getTag().toString())){ 97. imageView.setImageBitmap(bitmap); 98. }else{ 99. imageView.setImageResource(resId); 100. } 101. } 102. }; 103. } 104. 105. private Handler handler = new Handler(){ 106. 107. @Override 108. public void handleMessage(Message msg) { 109. // 子线程中返回的下载完成的任务 110. Task task = (Task)msg.obj; 111. // 调用callback对象的loadImage方法,并将图片路径和图片回传给adapter 112. task.callback.loadImage(task.path, task.bitmap); 113. } 114. 115. }; 116. 117. 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. }; 149. 150. //回调接口 151. public interface ImageCallback{ 152. void loadImage(String path, Bitmap bitmap); 153. } 154. 155. class Task{ 156. // 下载任务的下载路径 157. String path; 158. // 下载的图片 159. Bitmap bitmap; 160. // 回调对象 161. ImageCallback callback; 162. 163. @Override 164. public boolean equals(Object o) { 165. Task task = (Task)o; 166. return task.path.equals(path); 167. } 168. } 169.}
最后附上PicUtil类的代码,之前忘了贴这个类的代码,不好意识了~~
01.public class PicUtil { 02. private static final String TAG = "PicUtil"; 03. 04. /** 05. * 根据一个网络连接(URL)获取bitmapDrawable图像 06. * 07. * @param imageUri 08. * @return 09. */ 10. public static BitmapDrawable getfriendicon(URL imageUri) { 11. 12. BitmapDrawable icon = null; 13. try { 14. HttpURLConnection hp = (HttpURLConnection) imageUri 15. .openConnection(); 16. icon = new BitmapDrawable(hp.getInputStream());// 将输入流转换成bitmap 17. hp.disconnect();// 关闭连接 18. } catch (Exception e) { 19. } 20. return icon; 21. } 22. 23. /** 24. * 根据一个网络连接(String)获取bitmapDrawable图像 25. * 26. * @param imageUri 27. * @return 28. */ 29. public static BitmapDrawable getcontentPic(String imageUri) { 30. URL imgUrl = null; 31. try { 32. imgUrl = new URL(imageUri); 33. } catch (MalformedURLException e1) { 34. e1.printStackTrace(); 35. } 36. BitmapDrawable icon = null; 37. try { 38. HttpURLConnection hp = (HttpURLConnection) imgUrl.openConnection(); 39. icon = new BitmapDrawable(hp.getInputStream());// 将输入流转换成bitmap 40. hp.disconnect();// 关闭连接 41. } catch (Exception e) { 42. } 43. return icon; 44. } 45. 46. /** 47. * 根据一个网络连接(URL)获取bitmap图像 48. * 49. * @param imageUri 50. * @return 51. */ 52. public static Bitmap getusericon(URL imageUri) { 53. // 显示网络上的图片 54. URL myFileUrl = imageUri; 55. Bitmap bitmap = null; 56. try { 57. HttpURLConnection conn = (HttpURLConnection) myFileUrl 58. .openConnection(); 59. conn.setDoInput(true); 60. conn.connect(); 61. InputStream is = conn.getInputStream(); 62. bitmap = BitmapFactory.decodeStream(is); 63. is.close(); 64. } catch (IOException e) { 65. e.printStackTrace(); 66. } 67. return bitmap; 68. } 69. 70. /** 71. * 根据一个网络连接(String)获取bitmap图像 72. * 73. * @param imageUri 74. * @return 75. * @throws MalformedURLException 76. */ 77. public static Bitmap getbitmap(String imageUri) { 78. // 显示网络上的图片 79. Bitmap bitmap = null; 80. try { 81. URL myFileUrl = new URL(imageUri); 82. HttpURLConnection conn = (HttpURLConnection) myFileUrl 83. .openConnection(); 84. conn.setDoInput(true); 85. conn.connect(); 86. InputStream is = conn.getInputStream(); 87. bitmap = BitmapFactory.decodeStream(is); 88. is.close(); 89. 90. Log.i(TAG, "image download finished." + imageUri); 91. } catch (IOException e) { 92. e.printStackTrace(); 93. return null; 94. } 95. return bitmap; 96. } 97. 98. /** 99. * 下载图片 同时写道本地缓存文件中 100. * 101. * @param context 102. * @param imageUri 103. * @return 104. * @throws MalformedURLException 105. */ 106. public static Bitmap getbitmapAndwrite(String imageUri) { 107. Bitmap bitmap = null; 108. try { 109. // 显示网络上的图片 110. URL myFileUrl = new URL(imageUri); 111. HttpURLConnection conn = (HttpURLConnection) myFileUrl 112. .openConnection(); 113. conn.setDoInput(true); 114. conn.connect(); 115. 116. InputStream is = conn.getInputStream(); 117. File cacheFile = FileUtil.getCacheFile(imageUri); 118. BufferedOutputStream bos = null; 119. bos = new BufferedOutputStream(new FileOutputStream(cacheFile)); 120. Log.i(TAG, "write file to " + cacheFile.getCanonicalPath()); 121. 122. byte[] buf = new byte[1024]; 123. int len = 0; 124. // 将网络上的图片存储到本地 125. while ((len = is.read(buf)) > 0) { 126. bos.write(buf, 0, len); 127. } 128. 129. is.close(); 130. bos.close(); 131. 132. // 从本地加载图片 133. bitmap = BitmapFactory.decodeFile(cacheFile.getCanonicalPath()); 134. String name = MD5Util.MD5(imageUri); 135. 136. } catch (IOException e) { 137. e.printStackTrace(); 138. } 139. return bitmap; 140. } 141. 142. public static boolean downpic(String picName, Bitmap bitmap) { 143. boolean nowbol = false; 144. try { 145. File saveFile = new File("/mnt/sdcard/download/weibopic/" + picName 146. + ".png"); 147. if (!saveFile.exists()) { 148. saveFile.createNewFile(); 149. } 150. FileOutputStream saveFileOutputStream; 151. saveFileOutputStream = new FileOutputStream(saveFile); 152. nowbol = bitmap.compress(Bitmap.CompressFormat.PNG, 100, 153. saveFileOutputStream); 154. saveFileOutputStream.close(); 155. } catch (FileNotFoundException e) { 156. e.printStackTrace(); 157. } catch (IOException e) { 158. e.printStackTrace(); 159. } catch (Exception e) { 160. e.printStackTrace(); 161. } 162. return nowbol; 163. } 164. 165. public static void writeTofiles(Context context, Bitmap bitmap, 166. String filename) { 167. BufferedOutputStream outputStream = null; 168. try { 169. outputStream = new BufferedOutputStream(context.openFileOutput( 170. filename, Context.MODE_PRIVATE)); 171. bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream); 172. } catch (FileNotFoundException e) { 173. e.printStackTrace(); 174. } 175. } 176. 177. /** 178. * 将文件写入缓存系统中 179. * 180. * @param filename 181. * @param is 182. * @return 183. */ 184. public static String writefile(Context context, String filename, 185. InputStream is) { 186. BufferedInputStream inputStream = null; 187. BufferedOutputStream outputStream = null; 188. try { 189. inputStream = new BufferedInputStream(is); 190. outputStream = new BufferedOutputStream(context.openFileOutput( 191. filename, Context.MODE_PRIVATE)); 192. byte[] buffer = new byte[1024]; 193. int length; 194. while ((length = inputStream.read(buffer)) != -1) { 195. outputStream.write(buffer, 0, length); 196. } 197. } catch (Exception e) { 198. } finally { 199. if (inputStream != null) { 200. try { 201. inputStream.close(); 202. } catch (IOException e) { 203. e.printStackTrace(); 204. } 205. } 206. if (outputStream != null) { 207. try { 208. outputStream.flush(); 209. outputStream.close(); 210. } catch (IOException e) { 211. e.printStackTrace(); 212. } 213. } 214. } 215. return context.getFilesDir() + "/" + filename + ".jpg"; 216. } 217. 218. // 放大缩小图片 219. public static Bitmap zoomBitmap(Bitmap bitmap, int w, int h) { 220. int width = bitmap.getWidth(); 221. int height = bitmap.getHeight(); 222. Matrix matrix = new Matrix(); 223. float scaleWidht = ((float) w / width); 224. float scaleHeight = ((float) h / height); 225. matrix.postScale(scaleWidht, scaleHeight); 226. Bitmap newbmp = Bitmap.createBitmap(bitmap, 0, 0, width, height, 227. matrix, true); 228. return newbmp; 229. } 230. 231. // 将Drawable转化为Bitmap 232. public static Bitmap drawableToBitmap(Drawable drawable) { 233. int width = drawable.getIntrinsicWidth(); 234. int height = drawable.getIntrinsicHeight(); 235. Bitmap bitmap = Bitmap.createBitmap(width, height, drawable 236. .getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 237. : Bitmap.Config.RGB_565); 238. Canvas canvas = new Canvas(bitmap); 239. drawable.setBounds(0, 0, width, height); 240. drawable.draw(canvas); 241. return bitmap; 242. 243. } 244. 245. // 获得圆角图片的方法 246. public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, float roundPx) { 247. if(bitmap == null){ 248. return null; 249. } 250. 251. Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), 252. bitmap.getHeight(), Config.ARGB_8888); 253. Canvas canvas = new Canvas(output); 254. 255. final int color = 0xff424242; 256. final Paint paint = new Paint(); 257. final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); 258. final RectF rectF = new RectF(rect); 259. 260. paint.setAntiAlias(true); 261. canvas.drawARGB(0, 0, 0, 0); 262. paint.setColor(color); 263. canvas.drawRoundRect(rectF, roundPx, roundPx, paint); 264. 265. paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); 266. canvas.drawBitmap(bitmap, rect, rect, paint); 267. return output; 268. } 269. 270. // 获得带倒影的图片方法 271. public static Bitmap createReflectionImageWithOrigin(Bitmap bitmap) { 272. final int reflectionGap = 4; 273. int width = bitmap.getWidth(); 274. int height = bitmap.getHeight(); 275. 276. Matrix matrix = new Matrix(); 277. matrix.preScale(1, -1); 278. 279. Bitmap reflectionImage = Bitmap.createBitmap(bitmap, 0, height / 2, 280. width, height / 2, matrix, false); 281. 282. Bitmap bitmapWithReflection = Bitmap.createBitmap(width, 283. (height + height / 2), Config.ARGB_8888); 284. 285. Canvas canvas = new Canvas(bitmapWithReflection); 286. canvas.drawBitmap(bitmap, 0, 0, null); 287. Paint deafalutPaint = new Paint(); 288. canvas.drawRect(0, height, width, height + reflectionGap, deafalutPaint); 289. 290. canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null); 291. 292. Paint paint = new Paint(); 293. LinearGradient shader = new LinearGradient(0, bitmap.getHeight(), 0, 294. bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff, 295. 0x00ffffff, TileMode.CLAMP); 296. paint.setShader(shader); 297. // Set the Transfer mode to be porter duff and destination in 298. paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN)); 299. // Draw a rectangle using the paint with our linear gradient 300. canvas.drawRect(0, height, width, bitmapWithReflection.getHeight() 301. + reflectionGap, paint); 302. 303. return bitmapWithReflection; 304. } 305. 306.}
FileUtil
01.package com.wangge.coupon.util; 02. 03.import java.io.File; 04.import java.io.IOException; 05. 06.import android.os.Environment; 07.import android.util.Log; 08. 09.import com.wangge.coupon.http.AsynImageLoader; 10. 11.public class FileUtil { 12. private static final String TAG = "FileUtil"; 13. 14. public static File getCacheFile(String imageUri){ 15. File cacheFile = null; 16. try { 17. if (Environment.getExternalStorageState().equals( 18. Environment.MEDIA_MOUNTED)) { 19. File sdCardDir = Environment.getExternalStorageDirectory(); 20. String fileName = getFileName(imageUri); 21. File dir = new File(sdCardDir.getCanonicalPath() 22. + AsynImageLoader.CACHE_DIR); 23. if (!dir.exists()) { 24. dir.mkdirs(); 25. } 26. cacheFile = new File(dir, fileName); 27. Log.i(TAG, "exists:" + cacheFile.exists() + ",dir:" + dir + ",file:" + fileName); 28. } 29. } catch (IOException e) { 30. e.printStackTrace(); 31. Log.e(TAG, "getCacheFileError:" + e.getMessage()); 32. } 33. 34. return cacheFile; 35. } 36. 37. public static String getFileName(String path) { 38. int index = path.lastIndexOf("/"); 39. return path.substring(index + 1); 40. } 41.}