自己动手写android图片异步加载库

尊重他人劳动成果,转载请说明出处:

接触android有半年了,关于图片异步加载,一直只用别人的框架,虽然特别方便,,但是始终未见识到图片异步加载的庐山真面目。最近比较悠闲,研究一些高大上的东西。在这篇文章总结一下我对图片异步加载的一些学习心得。

图片加载最重要的无非就是内存和线程。大家都知道关于内存溢出一般的解决方案就是LruCache,在我的这个demo里我只要使用SoftReference实现了一个缓存类,SoftReference已经被遗弃了,这里只为学习。

代码

com.example.qtdemo_oom.Cache<T, U>

/** * 由SoftReference实现的内存缓存<br> * 此类仅供学习,由于Android 2.3开始,垃圾回收器倾向于回收软引用和弱引用对象。 * @author qingtian */public class Cache<T,U> {private Hashtable<T, NewSoftReference> hashTable;// 用于Chche内容的存储private ReferenceQueue<U> q;// 垃圾Reference的队列/** * 继承SoftReference,使得每一个实例都具有可识别的标识。 */private class NewSoftReference extends SoftReference<U> {public T key;public NewSoftReference(U em, ReferenceQueue<U> q) {super(em, q);}}/** * 构建一个缓存器实例 */public Cache() {hashTable = new Hashtable<T, NewSoftReference>();q = new ReferenceQueue<U>();}/** * 保存一个实例 * @param t * @param u */public void put(T t, U u) {cleanCache();// 清除垃圾引用NewSoftReference ref = new NewSoftReference(u, q);ref.key = t;hashTable.put(t, ref);}/** * 通过uri获取实例 * @param t * @return */public U get(T t) {U bm = null;if (hashTable.containsKey(t)) {NewSoftReference ref = (NewSoftReference) hashTable.get(t);bm = (U) ref.get();}return bm;}/** * 在hashTable里里清除已经被回收了的对象的软引用对象 */@SuppressWarnings("unchecked")private void cleanCache() {NewSoftReference ref = null;while ((ref = (NewSoftReference) q.poll()) != null) {hashTable.remove(ref.key);}}/** * 清除Cache内的全部内容 */public void clearCache() {cleanCache();hashTable.clear();System.gc();System.runFinalization();}}

com.example.qtdemo_oom.ImageLoader

/** * 图片加载工具类 * @author qingtian */public class ImageLoader {private static final String TAG = "qingtian" ;//线程池ExecutorService threadPool ;//自己实现的缓存类Cache<String, Bitmap> cache;//也可以用v4包提供的缓存//LruCache<String, Bitmap> cache;public ImageLoader() {threadPool = new ThreadPoolExecutor(2, 2, 0, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>());cache = new Cache<String, Bitmap>();//int maxMemory = (int) Runtime.getRuntime().maxMemory();//cache = new LruCache<String, Bitmap>(maxMemory/8){//// 测量Bitmap的大小//@Override//protected int sizeOf(String key, Bitmap value) {//return value.getRowBytes() * value.getHeight();//}//};}private int currentThreadNum = 0;class DownBitmapRunnable implements Runnable{ImageView iv; String uri;public DownBitmapRunnable( ImageView iv, String uri) {this.iv = iv;this.uri = uri;}@Overridepublic void run() {currentThreadNum++;show();Bitmap bm = cache.get(uri);if (bm == null) {Log.i(TAG, "下载");bm = BitmapUtil.getImageBitmap(uri);}else{Log.i(TAG, "不下载");}if (bm != null) {cache.put(uri, bm);final Bitmap fBitmap = bm;new Handler(Looper.getMainLooper()).post(new Runnable() {@Overridepublic void run() {iv.setImageBitmap(fBitmap);}});}currentThreadNum–;}}public void show( ImageView iv, String uri) {threadPool.execute(new DownBitmapRunnable(iv, uri));}public void show() {Log.i(TAG, "currentThreadNum:" + currentThreadNum );}}在这个类里,使用线程池管理线程,避免创建/取消线程时内存的浪费。第14行代码也提供了LruCache代码,我们也可以用LruCache来实现缓存。代码第54–61行,对于view的操作已经在主线程里了。

com.example.qtdemo_oom.Adapter

public class Adapter extends BaseAdapter {public static final String[] uris = new String[] {":8080/AndroidAsyncHttpService/image/img1b.jpg",":8080/AndroidAsyncHttpService/image/img2b.jpg",":8080/AndroidAsyncHttpService/image/img3b.jpg",":8080/AndroidAsyncHttpService/image/img4b.jpg",":8080/AndroidAsyncHttpService/image/img5b.jpg",":8080/AndroidAsyncHttpService/image/img6b.jpg",":8080/AndroidAsyncHttpService/image/img7b.jpg",":8080/AndroidAsyncHttpService/image/img8b.jpg",":8080/AndroidAsyncHttpService/image/img9b.jpg",":8080/AndroidAsyncHttpService/image/img10b.jpg",":8080/AndroidAsyncHttpService/image/img11b.jpg",":8080/AndroidAsyncHttpService/image/img12b.jpg",":8080/AndroidAsyncHttpService/image/img13b.jpg",":8080/AndroidAsyncHttpService/image/img14b.jpg",":8080/AndroidAsyncHttpService/image/img15b.jpg",":8080/AndroidAsyncHttpService/image/img16b.jpg",":8080/AndroidAsyncHttpService/image/img17b.jpg",":8080/AndroidAsyncHttpService/image/img18b.jpg",":8080/AndroidAsyncHttpService/image/img19b.jpg",":8080/AndroidAsyncHttpService/image/img20b.jpg",":8080/AndroidAsyncHttpService/image/img21b.jpg",":8080/AndroidAsyncHttpService/image/img22b.jpg" };public LayoutInflater mInflater;public ImageLoader loader;public Adapter(Context context) {mInflater = LayoutInflater.from(context);loader = new ImageLoader();}@Overridepublic int getCount() {return uris.length;}@Overridepublic Object getItem(int arg0) {return uris[arg0];}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder holder = null;if (convertView == null) {convertView = mInflater.inflate(R.layout.item, null);holder = new ViewHolder();holder.tv = (TextView) convertView.findViewById(R.id.tv);holder.iv = (ImageView) convertView.findViewById(R.id.iv);convertView.setTag(holder);} else {holder = (ViewHolder) convertView.getTag();}holder.tv.setText((String) getItem(position));loader.show(holder.iv, uris[position]);return convertView;}class ViewHolder {TextView tv;ImageView iv;}}代码第66行,就可以异步加载图片了。

com.example.qtdemo_oom.util.BitmapUtil

要想捉大鱼,不能怕水深。要想摘玫瑰,就得不怕刺。

自己动手写android图片异步加载库

相关文章:

你感兴趣的文章:

标签云: