本文来自:http://blog.csdn.net/wulianghuan/article/details/11548373,感谢原作者的分享。

目标是读取SD卡中的图片并且展示出来

主要思路是通过一个工具类来压缩来自sd卡中的图片,最后通过缓存机制来避免占用过多内存。

Util.java

package com.kale.socketactivity;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; public class Util { /**
* @param path
* @return
* @example Bitmap bitmap = BitmapFactory.decodeByteArray(Util.decodeBitmap(imagePath), 0, Util.decodeBitmap(imagePath).length);
imageCache.put(imagePath, new SoftReference<Bitmap>(bitmap)); //这里用了软引用
*/
public static byte[] decodeBitmap(String path) {
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;// 设置成了true,不占用内存,只获取bitmap宽高
BitmapFactory.decodeFile(path, opts);
opts.inSampleSize = computeSampleSize(opts, -1, 1024 * 800);
opts.inJustDecodeBounds = false;// 这里一定要将其设置回false,因为之前我们将其设置成了true
opts.inPurgeable = true;
opts.inInputShareable = true;
opts.inDither = false;
opts.inPurgeable = true;
opts.inTempStorage = new byte[16 * 1024];
FileInputStream is = null;
Bitmap bmp = null;
ByteArrayOutputStream baos = null;
try {
is = new FileInputStream(path);
//从文件中读取图片,可以换为别的方式
bmp = BitmapFactory.decodeFileDescriptor(is.getFD(), null, opts);
double scale = getScaling(opts.outWidth * opts.outHeight,
1024 * 600);
Bitmap bmp2 = Bitmap.createScaledBitmap(bmp,
(int) (opts.outWidth * scale),
(int) (opts.outHeight * scale), true);
bmp.recycle();
baos = new ByteArrayOutputStream();
bmp2.compress(Bitmap.CompressFormat.JPEG, 100, baos);
bmp2.recycle();
return baos.toByteArray();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
System.gc();
}
return baos.toByteArray();
} private static double getScaling(int src, int des) {
/**
* 48 目标尺寸÷原尺寸 sqrt开方,得出宽高百分比 49
*/
double scale = Math.sqrt((double) des / (double) src);
return scale;
} public static int computeSampleSize(BitmapFactory.Options options,
int minSideLength, int maxNumOfPixels) {
int initialSize = computeInitialSampleSize(options, minSideLength,
maxNumOfPixels); int roundedSize;
if (initialSize <= 8) {
roundedSize = 1;
while (roundedSize < initialSize) {
roundedSize <<= 1;
}
} else {
roundedSize = (initialSize + 7) / 8 * 8;
} return roundedSize;
} private static int computeInitialSampleSize(BitmapFactory.Options options,
int minSideLength, int maxNumOfPixels) {
double w = options.outWidth;
double h = options.outHeight; int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math
.sqrt(w * h / maxNumOfPixels));
int upperBound = (minSideLength == -1) ? 128 : (int) Math.min(
Math.floor(w / minSideLength), Math.floor(h / minSideLength)); if (upperBound < lowerBound) {
return lowerBound;
} if ((maxNumOfPixels == -1) && (minSideLength == -1)) {
return 1;
} else if (minSideLength == -1) {
return lowerBound;
} else {
return upperBound;
}
}
}

使用方式:

Bitmap bitmap = BitmapFactory.decodeByteArray(Util.decodeBitmap(imagePath), 0, Util.decodeBitmap(imagePath).length);
imageCache.put(imagePath, new SoftReference<Bitmap>(bitmap));

实现类

package com.pioneer.travel.util;

import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap; import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore;
import android.util.Log;
import android.widget.ImageView; public class AsyncImageLoaderByPath {
//SoftReference是软引用,是为了更好的为了系统回收变量
private HashMap<String, SoftReference<Bitmap>> imageCache;
private Context context; public AsyncImageLoaderByPath(Context context) {
this.imageCache = new HashMap<String, SoftReference<Bitmap>>();
this.context = context;
}
public Bitmap loadBitmapByPath(final String imagePath, final ImageView imageView, final ImageCallback imageCallback){
if (imageCache.containsKey(imagePath)) {
//从缓存中获取
SoftReference<Bitmap> softReference = imageCache.get(imagePath);
Bitmap bitmap = softReference.get();
if (bitmap != null) {
return bitmap;
}
}
final Handler handler = new Handler() {
public void handleMessage(Message message) {
imageCallback.imageLoaded((Bitmap) message.obj, imageView, imagePath);
}
};
//建立新一个获取SD卡的图片
new Thread() {
@Override
public void run() {
Bitmap bitmap = BitmapFactory.decodeByteArray(Util.decodeBitmap(imagePath), 0, Util.decodeBitmap(imagePath).length);
imageCache.put(imagePath, new SoftReference<Bitmap>(bitmap));
Message message = handler.obtainMessage(0, bitmap);
handler.sendMessage(message);
}
}.start();
return null;
}
//回调接口
public interface ImageCallback {
public void imageLoaded(Bitmap imageBitmap,ImageView imageView, String imagePath);
}
}

【转】解决Android因加载多个大图引起的OutOfMemoryError,内存溢出的问题的更多相关文章

  1. 彻底解决Android因加载多个大图引起的OutOfMemoryError,内存溢出的问题

    最近因为项目里需求是选择或者拍摄多张照片后,提供滑动预览和上传,很多照片是好几MB一张,因为目前的Android系统对运行的程序都有一定的内存限制,一般是16MB或24MB(视平台而定),不做处理直接 ...

  2. Android高效加载大图、多图解决方案,有效避免程序OOM

    高效加载大图片 我们在编写Android程序的时候经常要用到许多图片,不同图片总是会有不同的形状.不同的大小,但在大多数情况下,这些图片都会大于我们程序所需要的大小.比如说系统图片库里展示的图片大都是 ...

  3. Android图片加载库:最全面的Picasso讲解

    前言 上文已经对当今 Android主流的图片加载库 进行了全面介绍 & 对比 如果你还没阅读,我建议你先移步这里阅读 今天我们来学习其中一个Android主流的图片加载库的使用 - Pica ...

  4. 演化理解 Android 异步加载图片

    原文:http://www.cnblogs.com/ghj1976/archive/2011/05/06/2038738.html#3018499 在学习"Android异步加载图像小结&q ...

  5. Android 动态加载 (一) 态加载机制 案例一

    在目前的软硬件环境下,Native App与Web App在用户体验上有着明显的优势,但在实际项目中有些会因为业务的频繁变更而频繁的升级客户端,造成较差的用户体验,而这也恰恰是Web App的优势.本 ...

  6. fackbook的Fresco (FaceBook推出的Android图片加载库-Fresco)

    [Android开发经验]FaceBook推出的Android图片加载库-Fresco   欢迎关注ndroid-tech-frontier开源项目,定期翻译国外Android优质的技术.开源库.软件 ...

  7. Android Glide加载图片时转换为圆形、圆角、毛玻璃等图片效果

     Android Glide加载图片时转换为圆形.圆角.毛玻璃等图片效果 附录1简单介绍了Android开源的图片加载框架.在实际的开发中,虽然Glide解决了快速加载图片的问题,但还有一个问题悬 ...

  8. Android动态加载so文件

    在Android中调用动态库文件(*.so)都是通过jni的方式,而且往往在apk或jar包中调用so文件时,都要将对应so文件打包进apk或jar包,工程目录下图: 以上方式的存在的问题: 1.缺少 ...

  9. Android动态加载代码技术

    Android动态加载代码技术 在开发Android App的过程当中,可能希望实现插件式软件架构,将一部分代码以另外一个APK的形式单独发布,而在主程序中加载并执行这个APK中的代码. 实现这个任务 ...

随机推荐

  1. UVALive - 6709

    二维线段树单点修改板子题 #include<bits/stdc++.h> #define LL long long #define fi first #define se second # ...

  2. OLAP和OLTP基础知识

    数据处理大致可以分成两大类:联机事务处理OLTP(on-line transaction processing).联机分析处理OLAP(On-Line Analytical Processing).O ...

  3. ADNI数据集相关概念整理

    数据类型 临床 遗传 MRI图像 PET图像 生物样本 临床 ADNI临床数据集包括关于每个受试者的临床信息,包括招募,人口统计学,身体检查和认知评估数据.可以将整套临床数据作为逗号分隔值(CSV)文 ...

  4. 【GO基础】main redeclared in this block问题的排查与解决

    之前的GO练习环境放在虚拟机内,方便了不少.不过在liteIDE打开的情况下,我迁移了虚拟机,刚好两台机子的VMware版本还不同,这就导致了无法恢复挂起状态,我放弃了挂起. 重新启动后,为了继续练习 ...

  5. [转]01分数规划算法 ACM 二分 Dinkelbach 最优比率生成树 最优比率环

    01分数规划 前置技能 二分思想最短路算法一些数学脑细胞? 问题模型1 基本01分数规划问题 给定nn个二元组(valuei,costi)(valuei,costi),valueivaluei是选择此 ...

  6. Redis高可用之集群配置(六)

    0.Redis目录结构 1)Redis介绍及部署在CentOS7上(一) 2)Redis指令与数据结构(二) 3)Redis客户端连接以及持久化数据(三) 4)Redis高可用之主从复制实践(四) 5 ...

  7. 在mac中调试网页

    一.谷歌浏览器 //打开控制台 option + command + j 二.safari浏览器 safari > 偏好设置 > 勾选开发菜单 1.打开控制台 A.可以在网页中右键,检查元 ...

  8. GBDT算法

    GBDT通过多轮迭代,每轮迭代产生一个弱分类器,其中弱分类器通常选择为CART树,每个分类器在上一轮分类器的残差基础上进行训练. 对于GBDT算法,其中重要的知识点为: 1.GBDT是梯度下降法从参数 ...

  9. 面向对象设计原则 里氏替换原则(Liskov Substitution Principle)

    里氏替换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一. 里氏替换原则中说,任何基类可以出现的地方,子类一定可以出现. LSP是继承复用的基石,只 ...

  10. COGS NIOP联赛 图论相关算法总结

    最小生成树 Kruskal+ufs int ufs(int x) { return f[x] == x ? x : f[x] = ufs(f[x]); } int Kruskal() { int w ...