http://blog.csdn.net/yifei1989/article/details/19906821
最近在练习中用GridView加入相册中图片发现加入大量的相片之后,GirdView会变得很卡,想到或许可以用异步加载的方式来解决,但是能力有限,想得到却无法实现。在读了一些大牛的博客和代码之后,终于实现了。
1 在异步加载之前的代码的和普通加载代码一样,只需要在GirdView的Adapter的public View getView(int position, View convertView, ViewGroupparent)方法使用异步加载的方式返回ImageView。
2 如果能把加载过的图片给缓存起来,而不用每次都从sd卡上读取,这样效率应该会提高不少。所以可以先建一个缓存类,MemoryCache,为了能尽可能缓存,又尽可能的不抛出OOM的异常,可以使用SoftReference,软引用来缓冲图片。MemoryCache类的代码如下:
- /**
- * 缓存类(图片的路径和图片)
- */
- public class MemoryCache {
- private HashMap cache=new HashMap();
- //获取缓存图片
- public Bitmap get(String path) {
- if(cache.get(path)==null){
- return null;
- }else{
- return cache.get(path).get();
- }
- }
- //新增缓存
- public void put(String url,Bitmap bitmap) {
- cache.put(url, new SoftReference(bitmap));
- }
- //清空缓存
- public void clear() {
- cache.clear();
- }
- }
3 弄完了缓存类,接下来就可以弄异步加载的类,这个类主要在维护一个Stack,每次向这个类请求一个ImageView时,就要传入对应ImageView和图片的路径。异步类首先会根据图片的路径先去缓存中查找是否有缓存对应的BItMap,如果有就把他放到ImageView返回,如果没有就把这个ImageView和图片路径放到Stack中,并唤醒加载图片的线程。而加载图片的线程(线程优先权低于UI线程),会无限循环查看Stack大小,如果为0,就进入等待。如果不为0,就依次出栈Stack中的元素进行处理。(感觉像生产者-消费者模式)。
3.1 接下来,就写这个异步类的变量和构造函数了:
- private MemoryCache cache;
- private PhotosStack photosStack;
- private LoadImageThread loadImageThread;
- //用来保存每个月ImageView和对应应加载的图片
- private Map viewPath=Collections.synchronizedMap(new HashMap());
- public LoadImage(Activity activity) {
- super();
- cache=new MemoryCache();
- photosStack=new PhotosStack();
- loadImageThread=new LoadImageThread(activity);
- //设置异步加载线程优先权低于UI线程
- loadImageThread.setPriority(Thread.NORM_PRIORITY);
- }
其中MemoryCache是缓存类,PhotosStack类中维护一个Stack,LoadImageThread类是负责异步加载图片的。而viewPath这个变量是为了要保证GridView对应Position放对应的ImageView,如果没有这个变量,GridView中排列就会无序,在处理GridView的点击事件时候,就不好处理。而对viewPath的操作的异步,所以就需要线程安全咯。
PhotosStack代码如下:
- //维护需要被填充的Image和对应图片路径的栈
- class PhotosStack{
- Stack stack=new Stack();
- //移除指定ImageView
- public void remove(ImageView iView) {
- for(int i=0;i0){
- final MyPhoto photo;
- //得到栈顶的MyPhoto
- synchronized (photosStack.stack) {
- photo= photosStack.stack.pop();
- }
- cache.put(photo.path,getSmallBitmap(photo.path) );
- String ivPathString=viewPath.get(photo.imageView);
- if(ivPathString!=null&& ivPathString.equalsIgnoreCase(photo.path)){
- Runnable runableRunnable=new Runnable() {
- @Override
- public void run() {
- photo.imageView.setImageBitmap(getSmallBitmap(photo.path));
- }
- };
- activity.runOnUiThread(runableRunnable);
- }
- }
- if(photosStack.stack.size()==0){
- synchronized (photosStack.stack) {
- photosStack.stack.wait();
- }
- }
- } catch (InterruptedException e) {
- // TODO 自动生成的 catch 块
- e.printStackTrace();
- }
- }
- }
- }
其中缩小图片方法getSmallBitmap(String path),代码如下:
- //缩小图片
- public Bitmap getSmallBitmap(String path) {
- Options options=new Options();
- options.inJustDecodeBounds=true;
- BitmapFactory.decodeFile(path,options);
- int REQUIRE_SIZE=80;
- int scare=1;
- while(true){
- if(options.outWidth
关注打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?


微信扫码登录