关于LruCache和图片加载的封装

来源:互联网 发布:php 的curl. 编辑:程序博客网 时间:2024/04/23 20:32

前言

LruCache是用来在Android中实现内存缓存的,它是一个泛型类,内部采用LinkedHashMap以强引用的方式存储外界的缓存对象,提供了get和put方法获取和添加缓存对象,当缓存满时,LruCache会移除较早使用的缓存对象,然后再添加新的缓存对象。

  //maxMemory方法返回的堆内存的大小,单位是B,在此需要转化为KB        int maxSize = (int) (Runtime.getRuntime().maxMemory() / 1024);        int cacheSize = maxSize/8;        LruCache<String,Bitmap> lruCache = new LruCache<String,Bitmap>(cacheSize){            @Override            protected int sizeOf(String key, Bitmap bitmap) {                return bitmap.getRowBytes()*bitmap.getHeight()/1024;            }            @Override//移除旧缓存时会调用此方法,可以在此完成资源回收            protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) {                super.entryRemoved(evicted, key, oldValue, newValue);            }        };

另外LruCache是线程安全的,实现的方式是采用同步代码块,部分代码如下

   public void trimToSize(int maxSize) {        while (true) {            K key;            V value;            synchronized (this) {                if (size < 0 || (map.isEmpty() && size != 0)) {                    throw new IllegalStateException(getClass().getName()                            + ".sizeOf() is reporting inconsistent results!");                }                if (size <= maxSize) {                    break;                }                Map.Entry<K, V> toEvict = map.eldest();                if (toEvict == null) {                    break;                }                key = toEvict.getKey();                value = toEvict.getValue();                map.remove(key);                size -= safeSizeOf(key, value);                evictionCount++;            }            entryRemoved(true, key, value, null);        }    }

图片加载的封装

同步加载

同步加载需要在外部线程中调用,因为可能是耗时的操作

public Bitmap loadBitmap(String url,int reqWidth,int reqHeight){//判断是否是主线程,是的话抛出异常      if(Looper.myLooper()==Looper.getMainLooper()){            throw new RuntimeException("can't visit network form UI thread")        }    }

异步加载
创建一个Runnable对象,在里面去加载图片,通过Handler发送结果到主线程,然后在线程池里面去执行这个任务,
为什么要采用线程池:如果采用普通的线程,随着列表的滑动可能会产生大量的线程,这样不利于整体效率的提升

如何在子线程中创建Handler
两种方式:

  • 手动调用Looper.prepare和Looper.loop
   Looper.prepare();                Handler handler = new Handler(){                    @Override                    public void handleMessage(Message msg) {                        super.handleMessage(msg);                    }                };                Looper.loop();
  • 用主线程的Looper初始化Handler
 Handler handler = new Handler(Looper.getMainLooper()){                    @Override                    public void handleMessage(Message msg) {                        super.handleMessage(msg);                    }                };
0 0
原创粉丝点击