文档章节

安卓图片缓存技术

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

概述:随着手机硬件水平的提高及摩尔效应带来的成本的降低,用户手机上的图片的分辨率越来越高,而对于移动终端而言内存存在一定的限制的,如果程序占用过高的内存,也会抛出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版手机QQ的缓存监控与优化实践

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

JackJiang2011 ⋅ 04/08 ⋅ 0

Android Flutter 内存机制初探

阿里妹导读:闲鱼技术团队一直在探索如何使用Flutter来统一移动App开发。移动设备上的资源有限,内存使用成了日常开发中的常见问题。那么,Flutter是如何使用内存,又会对Native App的内存带...

b0q8cpra539hafs7 ⋅ 05/23 ⋅ 0

Android 性能优化:手把手教你优化Bitmap图片资源的使用

前言 在 开发中,性能优化策略十分重要 本文主要讲解性能优化中的Bitmap 使用优化,希望你们会喜欢 目录 1. 优化原因 即 为什么要优化图片资源,具体如下图:

Carson_Ho ⋅ 04/24 ⋅ 0

Design Patterns in Android:责任链模式

前言 非常抱歉,本系列博客长达半年没更新了,今日偶得灵感,更新一波《设计模式Android篇:责任链模式》。点击此处查看《Design Patterns in Android》系列其他文章。 本文原创作者MichaelX。...

MichaelX ⋅ 05/14 ⋅ 0

Android性能优化:手把手教你如何让App更快、更稳、更省(含内存、布局优化等)

前言 在 开发中,性能优化策略十分重要 因为其决定了应用程序的开发质量:可用性、流畅性、稳定性等,是提高用户留存率的关键 本文全面讲解性能优化中的所有知识,献上一份 性能优化的详细攻...

Carson_Ho ⋅ 05/30 ⋅ 0

【社招】招聘高级多媒体工程师-一家拥有15亿用户量的出海互联网企业

感兴趣的小伙伴请加我微信(2200624973) 岗位职责: 1、参与或者独立承担 Android 平台上媒体处理相关功能的设计、实现、测试及功能维护,参与或者独立承担方案或者架构选型。 2、参与产品的...

弓小嘿 ⋅ 05/17 ⋅ 0

Android开源框架源码鉴赏:VirtualAPK

关于作者 郭孝星,程序员,吉他手,主要从事Android平台基础架构方面的工作,欢迎交流技术方面的问题,可以去我的Github提issue或者发邮件至guoxiaoxingse@163.com与我交流。 文章目录 一 Vi...

郭孝星 ⋅ 02/10 ⋅ 0

android 读取WebView缓存及清理WebView缓存

1.缓存的分类: 首先要说的一点是缓存的分类,我们缓存的数据分为:页面缓存和数据缓存 页面缓存:加载一个网页时的html、JS、CSS等页面或者资源数据,这些缓存资源是由于浏览器 的行为而产生...

keller.zhou ⋅ 2016/11/15 ⋅ 0

Android Hybrid开发:这是一份详细 & 全面的WebView学习攻略

前言 现在很多里都内置了Web网页(),比如说很多电商平台,淘宝、京东、聚划算等等,如下图 那么这种该如何实现呢?其实这是里一个叫组件实现 今天,我将献上一份全面 & 详细的 攻略,含具体...

Carson_Ho ⋅ 前天 ⋅ 0

答CsdnBlogger问-关于安卓入行和开发问题

本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处! 问1:请问大牛对功能和框架的认识有哪些?(提问者:执笔记忆的空白) 比如对于一个小公司来说,什么样的框架最适用,您经...

liuzxgeek ⋅ 2016/09/21 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

【每天一个JQuery特效】根据可见状态确定是否显示或隐藏元素(3)

效果图示: 主要代码: <!DOCTYPE html><html><head><meta charset="UTF-8"><title>根据可见状态确定 是否显示或隐藏元素</title><script src="js/jquery-3.3.1.min.js" ty......

Rhymo-Wu ⋅ 28分钟前 ⋅ 0

OSChina 周四乱弹 —— 初中我身体就已经垮了,不知道为什么

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @加油东溪少年 :下完这场雨 后弦 《下完这场雨》- 后弦 手机党少年们想听歌,请使劲儿戳(这里) @马丁的代码 :买了日本 日本果然赢了 翻了...

小小编辑 ⋅ 47分钟前 ⋅ 7

浅谈springboot Web模式下的线程安全问题

我们在@RestController下,一般都是@AutoWired一些Service,由于这些Service都是单例,所以并不存在线程安全问题。 由于Controller本身是单例模式 (非线程安全的), 这意味着每个request过来,...

算法之名 ⋅ 今天 ⋅ 0

知乎Java数据结构

作者:匿名用户 链接:https://www.zhihu.com/question/35947829/answer/66113038 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 感觉知乎上嘲讽题主简...

颖伙虫 ⋅ 今天 ⋅ 0

Confluence 6 恢复一个站点有关使用站点导出为备份的说明

推荐使用生产备份策略。我们推荐你针对你的生产环境中使用的 Confluence 参考 Production Backup Strategy 页面中的内容进行备份和恢复(这个需要你备份你的数据库和 home 目录)。XML 导出备...

honeymose ⋅ 今天 ⋅ 0

JavaScript零基础入门——(九)JavaScript的函数

JavaScript零基础入门——(九)JavaScript的函数 欢迎回到我们的JavaScript零基础入门,上一节课我们了解了有关JS中数组的相关知识点,不知道大家有没有自己去敲一敲,消化一下?这一节课,...

JandenMa ⋅ 今天 ⋅ 0

火狐浏览器各版本下载及插件httprequest

各版本下载地址:http://ftp.mozilla.org/pub/mozilla.org//firefox/releases/ httprequest插件截至57版本可用

xiaoge2016 ⋅ 今天 ⋅ 0

Docker系列教程28-实战:使用Docker Compose运行ELK

原文:http://www.itmuch.com/docker/28-docker-compose-in-action-elk/,转载请说明出处。 ElasticSearch【存储】 Logtash【日志聚合器】 Kibana【界面】 答案: version: '2'services: ...

周立_ITMuch ⋅ 今天 ⋅ 0

使用快嘉sdkg极速搭建接口模拟系统

在具体项目研发过程中,一旦前后端双方约定好接口,前端和app同事就会希望后台同事可以尽快提供可供对接的接口方便调试,而对后台同事来说定好接口还仅是个开始、设计流程,实现业务逻辑,编...

fastjrun ⋅ 今天 ⋅ 0

PXE/KickStart 无人值守安装

导言 作为中小公司的运维,经常会遇到一些机械式的重复工作,例如:有时公司同时上线几十甚至上百台服务器,而且需要我们在短时间内完成系统安装。 常规的办法有什么? 光盘安装系统 ===> 一...

kangvcar ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部