文档章节

安卓图片缓存技术

htq
 htq
发布于 2016/07/26 09:41
字数 1216
阅读 7
收藏 1

概述:随着手机硬件水平的提高及摩尔效应带来的成本的降低,用户手机上的图片的分辨率越来越高,而对于移动终端而言内存存在一定的限制的,如果程序占用过高的内存,也会抛出OOM异常,降低了APP的用户体验感。另外自己做的APP应该尽可能的减少安装包的体积。本博客主要讲述通过压缩图片来减少安装包体积和通过使用图片缓存技术来高效加载大图。

一 压缩图片:

     在加载高分辨率图片的时候,最好先将图片进行压缩,一般情况下将图片压缩到大小与展示该图片的控件的大小差不多就可以。比如说:我们常用的腾讯QQ,在展示用户图像的控件上显示的实际上是压缩过的用户上传后的图片,当你要查看自己上传高清图像时,腾讯专门提供了一个查看大图的功能,此时才会将用户上传的图片显示出来,这样做的目的当然是为了减少程序占用的内存。

压缩图片主要是用到了安卓BitmapFactory.Options类,主要是通过设置options.inJustDecodeBounds = true; 这样就能在不将该bitmap加载到内存的情况下获得该图片的大小方面的属性,如:options.outHeight,options.outWidth。这样就可以根据需求对这些大小属性进行相应的压缩操作,记得在压缩操作完成后要设置options.inJustDecodeBounds = false;代码如下:
/**@author htq
 * 在该方法中对图片进行压缩,可以减少加载图片时占用的java内存。
 * @param path
 * @return
 */
	private Bitmap loadBitmapFromLocal(String path) {
		if (path == null) {
			return null;
		}
		
		BitmapFactory.Options options = new Options();
		options.inJustDecodeBounds = true;
		Bitmap bitmap = BitmapFactory.decodeFile(path, options);
		float height = 800f;
		float width = 480f;
		float scale = 1;
		if (options.outWidth > width && options.outWidth > options.outHeight) {
			scale = options.outWidth / width;
		} else if (options.outHeight > height
				&& options.outHeight > options.outWidth) {
			scale = options.outHeight / height;
		} else {
			scale = 1;
		}
		options.inSampleSize = (int) scale;
		options.inJustDecodeBounds = false;
		bitmap = BitmapFactory.decodeFile(path, options);
		bitmap = decodeBitmap(bitmap);
		if (!imgCaches.containsKey(path)) {
			//imgCaches.put(path, new SoftReference<Bitmap>(bitmap));
			addCache(path, bitmap);
		}
		return bitmap;
	}

除了减少图片占用程序运行的java内存外,还可以对图片进行质量压缩,不会减少图片的像素,所以转化为bitmap后java内存占用与压缩前相同,但可以用来减少图片的大小,即减少图片占用的磁盘空间。代码如下:
/**@author htq
	 * 该方法是对图片进行质量压缩,不会减少图片的像素,所以转化为bitmap后java内存占用与压缩前相同
	 * 仅仅用来减少图片的大小。
	 */
	private Bitmap decodeBitmap(Bitmap bitmap) {
		int scale = 100;
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		bitmap.compress(Bitmap.CompressFormat.JPEG, scale, bos);
		while ((bos.toByteArray().length / 1024) > 30) {
			bos.reset();
			bitmap.compress(Bitmap.CompressFormat.JPEG, scale, bos);
			scale -= 10;
		}
		ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
		bitmap = BitmapFactory.decodeStream(bis);
		return bitmap;
	}


二 使用图片缓存技术来高效加载大图
     2.1使用软引用来缓存图片:主要是通过一个HashMap来将图片路径和图片资源(用软引用表示)关联起来。代码如下:
private static HashMap<String, SoftReference<Bitmap>> imgCaches;
 imgCaches = new HashMap<String, SoftReference<Bitmap>>();
          具体加载图片步骤如下:
         1.通过path路径查看缓存中是否存在该图片,如果存在,则直接加载,如果不存在,则开启一个子线程从网络中获取。
2.图片下载完成后,将该图片放入到缓存中,供下次查询时使用。具体代码如下:

public void loadBitmap(final String path,
			final OnLoadBitmapListener listener) {
		final Handler handler = new Handler() {
			@Override
			public void handleMessage(Message msg) {
				super.handleMessage(msg);
				Bitmap bitmap = (Bitmap) msg.obj;
				listener.loadImage(bitmap, path);
			}
		};
		new Thread() {

			@Override
			public void run() {
				executorThreadPool.execute(new Runnable() {
					@Override
					public void run() {
						Bitmap bitmap = loadBitmapFromCache(path);
						if (bitmap != null) {
							Message msg = handler.obtainMessage();
							msg.obj = bitmap;
							handler.sendMessage(msg);
						}

					}
				});
			}

		}.start();
	}


    2.2内存缓存技术:主要是通过LruCache这个类来缓存图片,故名思意可知,当缓存的图片达到了预先设定的值的时候,那么近期使用次数最少的图片就会被回收掉。

使用该类时要预先设置缓存图片内存大小,且必须重写该类的sizeof()方法,默认返回图片数量。代码如下:

private LruCache<String, Bitmap> mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
		@Override
		protected int sizeOf(String key, Bitmap bitmap) {
			// 重写此方法来衡量每张图片的大小,默认返回图片数量。
			return bitmap.getByteCount() / 1024;
		}
	};

与上述使用软引用来加载缓存图片类似,首先会在 LruCache 的缓存中进行检查。如果找到了该图片的缓存,则直接加载,否则开启一个后台线程来加载这张图片。代码如下:
<pre name="code" class="html">public synchronized void addBitmapToMemoryCache(String key, Bitmap bitmap) {
        if (mMemoryCache.get(key) == null) {
            if (key != null && bitmap != null)
                mMemoryCache.put(key, bitmap);
        } else
            Log.w(TAG, "the res is aready exits");
    }

    public synchronized Bitmap getBitmapFromMemCache(String key) {
        Bitmap bm = mMemoryCache.get(key);
        if (key != null) {
            return bm;
        }
        return null;
    }

/**
     * 移除缓存
     * 
     * @param key
     */
    public synchronized void removeImageCache(String key) {
        if (key != null) {
            if (mMemoryCache != null) {
                Bitmap bm = mMemoryCache.remove(key);
                if (bm != null)
                    bm.recycle();
            }
        }
    }


        
   


本文转载自:http://blog.csdn.net/htq__/article/details/50935707

共有 人打赏支持
htq

htq

粉丝 19
博文 67
码字总数 1007
作品 3
武汉
私信 提问
为什么Android官方废弃SoftRefrerence软引用和WeakReference弱引用,而拥抱LruCache?

为什么Android官方废弃SoftRefrerence软引用和WeakReference弱引用,而拥抱LruCache? 一些具有Java背景的研发者喜欢使用软引用(SoftRefrerence)和弱引用(WeakReference)来缓存Java对象和数据...

开开心心过
06/09
0
0
android 图片加载之边下载边显示的讨论。

最近,接触的项目的图片加载都有不少的应用。大概了解了,不外乎一下几种,或者兼顾几种做法: |-采用缓存来提高用户体验,也节约流量。 |-缓存上做文章,采用多种策略的缓存模式,来达到更加...

Justin_Chiang
2013/12/25
1K
7
Android开发优化之——对Bitmap的内存优化

在Android应用里,最耗费内存的就是图片资源。而且在Android系统中,读取位图Bitmap时,分给虚拟机中的图片的堆栈大小只有8M,如果超出了,就会出现OutOfMemory异常。所以,对于图片的内存优...

KingMing
2015/04/03
0
0
腾讯技术分享:Android版手机QQ的缓存监控与优化实践

本文内容整理自公众号腾讯Bugly,感谢原作者的分享。 1、问题背景 对于Android应用来说,内存向来是比较重要的性能指标。内存占用过高,会影响应用的流畅度,甚至引发OOM,非常影响用户体验。...

JackJiang2011
04/08
0
0
[Android] Android开发优化之——对Bitmap的内存优化

在Android应用里,最耗费内存的就是图片资源。而且在Android系统中,读取位图Bitmap时,分给虚拟机中的图片的堆栈大小只有8M,如果超出了,就会出现OutOfMemory异常。所以,对于图片的内存优...

haman
2014/01/25
0
1

没有更多内容

加载失败,请刷新页面

加载更多

EOS docker开发环境

使用eos docker镜像是部署本地EOS开发环境的最轻松愉快的方法。使用官方提供的eos docker镜像,你可以快速建立一个eos开发环境,可以迅速启动开发节点和钱包服务器、创建账户、编写智能合约....

汇智网教程
今天
12
0
《唐史原来超有趣》的读后感优秀范文3700字

《唐史原来超有趣》的读后感优秀范文3700字: 作者:花若离。我今天分享的内容《唐史原来超有趣》这本书的读后感,我将这本书看了一遍之后就束之高阁了,不过里面的内容一直在在脑海中回放,...

原创小博客
今天
19
0
IC-CAD Methodology知识图谱

CAD (Computer Aided Design),计算机辅助设计,指利用计算机及其图形设备帮助设计人员进行设计工作,这个定义同样可以用来近似描述IC公司CAD工程师这个岗位的工作。 早期IC公司的CAD岗位最初...

李艳青1987
今天
18
0
CompletableFuture get方法一直阻塞或抛出TimeoutException

问题描述 最近刚刚上线的服务突然抛出大量的TimeoutException,查询后发现是使用了CompletableFuture,并且在执行future.get(5, TimeUnit.SECONDS);时抛出了TimeoutException异常,导致接口响...

xiaolyuh
今天
9
0
dubbo 搭建与使用

官网:http://dubbo.apache.org/en-us/ 一,安装监控中心(可以不安装) admin管理控制台,monitor监控中心 下载 bubbo ops 这个是新版的,需要node.js环境,我没有就用老版的了...

小兵胖胖
今天
18
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部