import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.util.Log; import java.io.*; import java.util.*; public final class BitMapUtil { private static final Size ZERO_SIZE = new Size(0, 0); private static final BitmapFactory.Options OPTIONS_GET_SIZE = new BitmapFactory.Options(); private static final BitmapFactory.Options OPTIONS_DECODE = new BitmapFactory.Options(); private static final byte[] LOCKED = new byte[0]; // 此对象用来保持Bitmap的回收顺序,保证最后使用的图片被回收 private static final LinkedList<String> CACHE_ENTRIES = new LinkedList<String>(); // 线程请求创建图片的队列 private static final Queue<QueueEntry> TASK_QUEUE = new LinkedList<QueueEntry>(); // 保存队列中正在处理的图片的key,有效防止重复添加到请求创建队列 private static final Set TASK_QUEUE_INDEX = new HashSet(); // 缓存Bitmap // 通过图片路径,图片大小 private static final Map<String, Bitmap> IMG_CACHE_INDEX = new HashMap<String, Bitmap>(); private static int CACHE_SIZE = 20; // 缓存图片数量 static { OPTIONS_GET_SIZE.inJustDecodeBounds = true; // 初始化创建图片线程,并等待处理 new Thread() { { setDaemon(true); } public void run() { while (true) { synchronized (TASK_QUEUE) { if (TASK_QUEUE.isEmpty()) { try { TASK_QUEUE.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } QueueEntry entry = TASK_QUEUE.poll(); String key = createKey(entry.path, entry.width, entry.height); TASK_QUEUE_INDEX.remove(key); createBitmap(entry.path, entry.width, entry.height); } } }.start(); } public static Bitmap getBitmap(String path, int width, int height) { if(path==null){ return null; } Bitmap bitMap = null; try { if (CACHE_ENTRIES.size() >= CACHE_SIZE) { destoryLast(); } bitMap = useBitmap(path, width, height); if (bitMap != null && !bitMap.isRecycled()) { return bitMap; } bitMap = createBitmap(path, width, height); String key = createKey(path, width, height); synchronized (LOCKED) { IMG_CACHE_INDEX.put(key, bitMap); CACHE_ENTRIES.addFirst(key); } } catch (OutOfMemoryError err) { destoryLast(); System.out.println(CACHE_SIZE); return createBitmap(path, width, height); } return bitMap; } public static Size getBitMapSize(String path) { File file = new File(path); if (file.exists()) { InputStream in = null; try { in = new FileInputStream(file); BitmapFactory.decodeStream(in, null, OPTIONS_GET_SIZE); return new Size(OPTIONS_GET_SIZE.outWidth, OPTIONS_GET_SIZE.outHeight); } catch (FileNotFoundException e) { return ZERO_SIZE; } finally { closeInputStream(in); } } return ZERO_SIZE; } // 将图片加入队列头 private static Bitmap useBitmap(String path, int width, int height) { Bitmap bitMap = null; String key = createKey(path, width, height); synchronized (LOCKED) { bitMap = IMG_CACHE_INDEX.get(key); if (null != bitMap) { if (CACHE_ENTRIES.remove(key)) { CACHE_ENTRIES.addFirst(key); } } } return bitMap; } // 回收最后一张图片 private static void destoryLast() { synchronized (LOCKED) { String key = CACHE_ENTRIES.removeLast(); if (key.length() > 0) { Bitmap bitMap = IMG_CACHE_INDEX.remove(key); if (bitMap != null && !bitMap.isRecycled()) { bitMap.recycle(); bitMap = null; } } } } // 创建键 private static String createKey(String path, int width, int height) { if (null == path || path.length() == 0) { return ""; } return path + "_" + width + "_" + height; } // 通过图片路径,宽度高度创建一个Bitmap对象 private static Bitmap createBitmap(String path, int width, int height) { File file = new File(path); if (file.exists()) { InputStream in = null; try { in = new FileInputStream(file); Size size = getBitMapSize(path); if (size.equals(ZERO_SIZE)) { return null; } int scale = 1; int a = size.getWidth() / width; int b = size.getHeight() / height; scale = Math.max(a, b); synchronized (OPTIONS_DECODE) { OPTIONS_DECODE.inSampleSize = scale; Bitmap bitMap = BitmapFactory.decodeStream(in, null, OPTIONS_DECODE); return bitMap; } } catch (FileNotFoundException e) { Log.v("BitMapUtil","createBitmap=="+e.toString()); } finally { closeInputStream(in); } } return null; } // 关闭输入流 private static void closeInputStream(InputStream in) { if (null != in) { try { in.close(); } catch (IOException e) { Log.v("BitMapUtil", "closeInputStream==" + e.toString()); } } } // 图片大小 static class Size { private int width, height; Size(int width, int height) { this.width = width; this.height = height; } public int getWidth() { return width; } public int getHeight() { return height; } } // 队列缓存参数对象 static class QueueEntry { public String path; public int width; public int height; } }
相关推荐
JPEGKIT将LIJPEG Turbo C 库桥接到Android中,并用一个易于使用的类来封装它。您当前可以:
主要介绍了SQL Server出现System.OutOfMemoryException异常的解决方法,同时提供了微软官方的解决方案,需要的朋友可以参考下
在什么情况下会出现OutOfMemonryException呢? 在我们试图新建一个对象时,而垃圾收集器又找不到任何可用内存时被抛出,这种情况下我们是可以捕获该 异常的; 另一种情况是,CLR需要内存时,而却系统却不能提供,也会抛出...
Java 内存泄露 解决方案 outofmemoryException 从实践获取真理
使用Spire.Pdf添加水印,提示“System.OutOfMemoryException”异常和“未将对象引用设置到对象的实例”
1.StackOverFlowException (一般来说这个不是真的堆栈不够了,而是你的代码出现了无线递归),如果你用throw new StackOverFlowException 还是可以catch的2.OutOfMemoryException (好像只有 box newarr newobj 才会抛...
我们在开发过程中曾经遇到过一个奇怪的问题:当软件加载了很多比较大规模的数据后,会偶尔出现OutOfMemoryException异常,但通过内存检查工具却发现还有很多可用内存。于是我们怀疑是可用内存总量充足,但却没有足够...
产服务器宕机。从当时的日志情况来看请求操作失败,资源等待操作,,现实抛出内存溢出(OutOfMemoryException)异常
You can now double-click the appstart.jar and your application is started, without hideous DOS windows, class-path headhaches or fears of the dreaded OutOfMemoryException. ...
对于多线程,您需要考虑线程安全,并且它可能会意外崩溃(例如OutOfMemoryException)并且所有线程都中止。如果您使用 jvmpart 进行处理,则一个崩溃永远不会影响其他崩溃,所有 JVM 进程都是独立运行的,并且与它...
JanusGraph over HBase支持全局顶点和边缘...但是,请注意,所有这些顶点和/或边都将加载到内存中,这可能会导致OutOfMemoryException。使用JanusGraph和TinkerPop的Hadoop-Gremlin有效地遍历大型图中的所有顶点或边。
这种尝试的结果应该可以实现该存储实现的生产就绪使用,并处理内存处理的特定属性,例如不惜一切代价避免OutOfMemoryException并在垃圾回收上减轻负担。 当然,我们不能完全避免它们,但至少可以以某种方式控制它们...
我无法帮助解决与“OutOfMemoryException”错误相关的任何事情。 我建议为每个工具使用提供的 powershell 脚本(.ps1 文件)(带有必要的个人编辑)。 默认情况下,脚本被设置为使用syncMode 0(同步),因此,...
需要从JVM OutOfMemoryException(OME)中恢复JVM具有-XX:OnOutOfMemoryError选项,该选项可让您在脚本因OME而死时运行。 这是如何使用它的一个例子。 startTest.sh启动一个Java程序,该Java程序在内存不足的情况下...
7.3.7 OutOfMemoryException 187 7.3.8 ComException、SEHException及其他CLR异常 188 7.3.9 ExecutionEngineException 188 7.4 自定义异常的设计 188 7.5 异常与性能 190 7.5.1 Tester-Doer模式 190 ...
7.3.7 OutOfMemoryException 187 7.3.8 ComException、SEHException及其他CLR异常 188 7.3.9 ExecutionEngineException 188 7.4 自定义异常的设计 188 7.5 异常与性能 190 7.5.1 Tester-Doer模式 190 ...