前言
其实很幸运,入职一周之后就能跟着两个师兄做androID开发,师兄都是大神,身为小白的我只能多多学习,多多努力。最近一段时间都忙的没机会总结,今天刚完成了androID客户端图片异步加载的类,这里记录一下(ps:其实我这里都是参考网上开源实现)
原理
在ListVIEw或者GrIDVIEw中加载图片的原理基本都是一样的:
先从内存缓存中获取,取到则返回,取不到进行下一步
从文件缓存中获取,取到则返回并更新到内存缓存,取不到则进行进行下一步
从网络上下载图片,并更新内存缓存和文件缓存
流程图如下:
同时,要注意线程的数量。一般在ListvIEw中加载图片,大家都是开启新的线程去加载,但是当快速滑动时,很容易造成OOM,因此需要控制线程数量。我们可以通过线程池控制线程的数量,具体线程池的大小还需要根据处理器的情况和业务情况自行判断
建立线程池的方法如下:
ExecutorService executorService = Executors.newFixedThreadPool(5); // 5是可变的
文件缓存类
import java.io.file; import androID.content.Context; public class fileCache { private static final String DIR_name = "your_dir"; private file cacheDir; public fileCache(Context context) { // Find the directory to save cached images if (androID.os.Environment.getExternalStorageState().equals( androID.os.Environment.MEDIA_MOUNTED)) { cacheDir = new file( androID.os.Environment.getExternalStorageDirectory(),DIR_name); } else { cacheDir = context.getCacheDir(); } if (!cacheDir.exists()) { cacheDir.mkdirs(); } } public file getfile(String url) { // IDentify images by url's hash code String filename = String.valueOf(url.hashCode()); file f = new file(cacheDir,filename); return f; } public voID clear() { file[] files = cacheDir.Listfiles(); if (files == null) { return; } else { for (file f : files) { f.delete(); } } } }
内存缓存类
这里使用了软引用,Map<String,SoftReference<Bitmap>> cache,可以Google一下软引用的机制,简单的说:实现了map,同时当内存紧张时可以被回收,不会造成内存泄露
import java.lang.ref.softReference; import java.util.Collections; import java.util.linkedHashMap; import java.util.Map; import androID.graphics.Bitmap; public class MemoryCache { private Map<String,SoftReference<Bitmap>> cache = Collections .synchronizedMap(new linkedHashMap<String,SoftReference<Bitmap>>( 10,1.5f,true)); public Bitmap get(String ID) { if (!cache.containsKey(ID)) { return null; } SoftReference<Bitmap> ref = cache.get(ID); return ref.get(); } public voID put(String ID,Bitmap bitmap) { cache.put(ID,new SoftReference<Bitmap>(bitmap)); } public voID clear() { cache.clear(); } }
图片加载类
import java.io.file; import java.io.fileinputStream; import java.io.fileNotFoundException; import java.io.fileOutputStream; import java.io.inputStream; import java.io.OutputStream; import java.net.httpURLConnection; import java.net.URL; import java.util.Collections; import java.util.Map; import java.util.WeakHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import androID.content.Context; import androID.graphics.Bitmap; import androID.graphics.BitmapFactory; import androID.os.Handler; import androID.Widget.ImageVIEw; public class ImageLoader { /** * Network time out */ private static final int TIME_OUT = 30000; /** * Default picture resource */ private static final int DEFAulT_BG = R.drawable.plate_List_head_bg; /** * Thread pool number */ private static final int THREAD_NUM = 5; /** * Memory image cache */ MemoryCache memoryCache = new MemoryCache(); /** * file image cache */ fileCache fileCache; /** * Judge image vIEw if it is reuse */ private Map<ImageVIEw,String> imageVIEws = Collections .synchronizedMap(new WeakHashMap<ImageVIEw,String>()); /** * Thread pool */ ExecutorService executorService; /** * Handler to display images in UI thread */ Handler handler = new Handler(); public ImageLoader(Context context) { fileCache = new fileCache(context); executorService = Executors.newFixedThreadPool(THREAD_NUM); } public voID disPlayImage(String url,ImageVIEw imageVIEw) { imageVIEws.put(imageVIEw,url); Bitmap bitmap = memoryCache.get(url); if (bitmap != null) { // display image from Memory cache imageVIEw.setimageBitmap(bitmap); } else { // display image from file cache or Network queuePhoto(url,imageVIEw); } } private voID queuePhoto(String url,ImageVIEw imageVIEw) { PhotoToload photoToload = new PhotoToload(url,imageVIEw); executorService.submit(new Photosloader(photoToload)); } private Bitmap getBitmap(String url) { file f = fileCache.getfile(url); // From file cache Bitmap bmp = decodefile(f); if (bmp != null) { return bmp; } // From Network try { Bitmap bitmap = null; URL imageUrl = new URL(url); httpURLConnection conn = (httpURLConnection) imageUrl .openConnection(); conn.setConnectTimeout(TIME_OUT); conn.setReadTimeout(TIME_OUT); conn.setInstanceFollowRedirects(true); inputStream is = conn.getinputStream(); OutputStream os = new fileOutputStream(f); copyStream(is,os); os.close(); conn.disconnect(); bitmap = decodefile(f); return bitmap; } catch (Throwable ex) { if (ex instanceof OutOfMemoryError) { clearCache(); } return null; } } private voID copyStream(inputStream is,OutputStream os) { int buffer_size = 1024; try { byte[] bytes = new byte[buffer_size]; while (true) { int count = is.read(bytes,buffer_size); if (count == -1) { break; } os.write(bytes,count); } } catch (Exception e) { } } private Bitmap decodefile(file f) { try { // Todo:Compress image size fileinputStream fileinputStream = new fileinputStream(f); Bitmap bitmap = BitmapFactory.decodeStream(fileinputStream); return bitmap; } catch (fileNotFoundException e) { return null; } } private voID clearCache() { memoryCache.clear(); fileCache.clear(); } /** * Task for the queue * * @author zhengyi.wzy * */ private class PhotoToload { public String url; public ImageVIEw imageVIEw; public PhotoToload(String url,ImageVIEw imageVIEw) { this.url = url; this.imageVIEw = imageVIEw; } } /** * Asynchronous to load picture * * @author zhengyi.wzy * */ class Photosloader implements Runnable { PhotoToload photoToload; public Photosloader(PhotoToload photoToload) { this.photoToload = photoToload; } private boolean imageVIEwReused(PhotoToload photoToload) { String tag = imageVIEws.get(photoToload.imageVIEw); if (tag == null || !tag.equals(photoToload.url)) { return true; } return false; } @OverrIDe public voID run() { // Abort current thread if Image VIEw reused if (imageVIEwReused(photoToload)) { return; } Bitmap bitmap = getBitmap(photoToload.url); // Update Memory memoryCache.put(photoToload.url,bitmap); if (imageVIEwReused(photoToload)) { return; } // Don't change UI in children thread Bitmapdisplayer bd = new Bitmapdisplayer(bitmap,photoToload); handler.post(bd); } class Bitmapdisplayer implements Runnable { Bitmap bitmap; PhotoToload photoToload; public Bitmapdisplayer(Bitmap bitmap,PhotoToload photoToload) { this.bitmap = bitmap; this.photoToload = photoToload; } @OverrIDe public voID run() { if (imageVIEwReused(photoToload)) { return; } if (bitmap != null) { photoToload.imageVIEw.setimageBitmap(bitmap); } else { photoToload.imageVIEw.setimageResource(DEFAulT_BG); } } } } }
调用方法
ImageLoader imageLoader = new ImageLoader(context); imageLoader.disPlayImage(imageUrl,imageVIEw);
总结
以上是内存溢出为你收集整理的在Android的应用中实现网络图片异步加载的方法全部内容,希望文章能够帮你解决在Android的应用中实现网络图片异步加载的方法所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)