android bitmap转file 回收后,没有数据了怎么办

【图片】【求助】SoftReference为什么不回收bitmap?【android开发吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:116,745贴子:
【求助】SoftReference为什么不回收bitmap?收藏
大家好,我是android开放初学者,现在遇到了一个内存溢出的问题希望大家帮忙看看。谢谢!我现在做的是一个图片分享的应用,需要加载大量图片,会消耗内存在网上搜索了一些资料,很多都是用软引用SoftReference如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存可是我不明白,为什么我用了SoftReference,却不进行回收,下面是我的代码:工具类:调用:Bitmap bitmap = BitmapCache.getInstance().getBitmap(Imgurl, this);imgView.setImageBitmap(bitmap);运行程序,第一次访问下面的界面:打印日志:第二次访问上面的界面,打印日志:这些日志都有正常打印,可是下面这段代码中的while代码段却直到内存溢出都未曾执行过:这段代码是检查哪个SoftReference所软引用的对象已经被回收,把这些失去软引用的对象的SoftReference对象清除掉,可是这里面的代码直到内存溢出了都从来就没执行过,也就是根本没有SoftReference所软引用的对象被回收如果(ref = (BtimapRef) q.poll()) != null成立,则证明此对象已被回收,则执行while里面的代码:bitmapRefs.remove(ref._key);否则,对象未被回收,while里面的代码不会执行我不明白,这到底是为什么,内存不足了却不回收?
达内android开发,开启安卓“薪”时代,前沿安卓课程,120天速成安卓高级工程师,达内android开发,短期打造编程高手!点击申请-达内免费试学&&
补充:第一次访问打印日志的截图:
GC_FOR_ALLOC freed ...那行是系统回收了内存的记录,这个操作,用户程序看不到。另,我经常十来兆内存被GC,也没出现程序崩溃问题啊?
@shysnower我的项目有很多个界面,几乎每个界面都是图片当我不断的访问各个界面,到了一定程度,就会内存溢出
登录百度帐号推荐应用1720人阅读
& & & &今天来研究一下android中的Bitmap。在实际开发中,Bitmap经常用到,特别是游戏开发。可以说游戏开发其实就是对图片(Bitmap)操作!可见Bitmap有多重要。这里我们主要讨论的是Bitmap资源释放原理。
& & & & 我们知道,用完一个Bitmap后,需要马上recycle()来保证尽快释放期资源。首先,我们来看看recycle()这个函数的定义(Bitmap.java):
public void recycle() {
if (!mRecycled) {
if (nativeRecycle(mNativeBitmap)) {
// return value indicates whether native pixel object was actually recycled.
// false indicates that it is still in use at the native level and these
// objects should not be collected now. They will be collected later when the
// Bitmap itself is collected.
mNinePatchChunk =
mRecycled =
} 代码很简单,主要调用这个函数:nativeRecycle(mNativeBitmap)去释放。这里是JNI方式去调用了c写的方法!其实,你看看一下Bitmap这个类,就知道了,其实Bitmap的实现主要都是用C写的,为了保证效率这样选择是必然的! 这不是我们讨论的重点。我们来看看google给这个函数的一段说明:
* Free the native object associated with this bitmap, and clear the
* reference to the pixel data. This will not free the pixe
* it simply allows it to be garbage collected if there are no other references.
* The bitmap is marked as &dead&, meaning it will throw an exception if
* getPixels() or setPixels() is called, and will draw nothing. This operation
* cannot be reversed, so it should only be called if you are sure there are no
* further uses for the bitmap. This is an advanced call, and normally need
* not be called, since the normal GC process will free up this memory when
* there are no more references to this bitmap.
*/ 通过这段说明我们知道调用这个函数其实只是会free一些相关的资源、对于其t图片像素数据并没有同步释放,而且这个方法通常也不是必要的,就是说:不是一定要调用这个函数这个Bitmap才会被GC回收。那么问题就来了:刚才说了,那图片像素这类数据是如何释放的呢?最重要的是bitmap处理的核心代码不是JAVA写的。
& & & &这个时候finalize()就登场了。我们先看看里面定义的一个私有变量private final BitmapFinalizer mF&BitmapFinalizer 是Bitmap的内部类:
private static class BitmapFinalizer {
private final int mNativeB
BitmapFinalizer(int nativeBitmap) {
mNativeBitmap = nativeB
public void finalize() {
super.finalize();
} catch (Throwable t) {
} finally {
nativeDestructor(mNativeBitmap);
}& & & &这里很好的利用object的finalize()这个回调函数,这样就来保证一个Bitmap对象被释放的时候能够回调void nativeDestructor(int nativeBitmap);这个函数来释放C里面申请的资源!
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:85185次
积分:1436
积分:1436
排名:千里之外
原创:51篇
转载:24篇
评论:20条
(1)(2)(1)(3)(1)(14)(7)(3)(5)(2)(2)(1)(1)(2)(1)(5)(20)(4)(3)Posts - 91,
Articles - 0,
Comments - 90
11:13 by onm, ... 阅读,
Android3.0之前的手机,通过DDMS观看Heap信息的时候不显示native部分分配的内存大小,如图所示,加载了一张7M多的图片,但是显示分配Allocated才2M多。但是native分配的内存大小是算在heap上的,所以当heap大小显示的不是HeapMaxSize的时候,也有可能oom。
下图是Android3.0之前Bitmap的内存管理方式。
3.0以后情况。
3.0以后Bitmap内存管理方式。
3.0以后Bitmap分配的内存是受GC管理的内存,分配站Heap上,可以通过GC回收。3.0之前是freed via recycle() or finalizer。
3.0以前LogCat会出现类似external_alloc相关字样,应该就是上图中Native中分配的内存。
还有GC_EXTERNAL_ALLOC,表示GC to try to reduce heap footprint to allow more non-GC'ed memory.
可以通过GC_EXPLICIT freed &1K, 50% free K, external 1K, paused 54ms,观察到external的内存占用,使用了19447K,总共21495K。free后面显示的是分配在Heap上的内存。
网上有这么说的“external是指VM中通过JNI中Native的类中的malloc分配出的内存,例如Bitmap和一些Cursor都是这么分配的”。
而且发现,通过BitmapFactory decode的时候,Android4.0和Android2.3分配的内存空间是不一样的,Android4.0分配的空间是Android2.3的2倍。(没有具体考察具体的分界线是哪个版本)
这个可以在decode的时候通过设置Options来更改,inPreferredConfig属性决定了,Bitmap.Config类型,Config有常用的有RGB_565,ARGB_8888两种,正好对应了刚才说的情况。RGB_565是每个像素用2个字节存储,只存储R、G、B信息,分别占用5、6、6个bit,没有alpha信息。而RGB_8888是每个像素用4个字节存储,A、R、G、B分别用8bit存储。当然这种图片的质量更高。
还有一个疑问是我的图片是7.8M的一张图片,但是加在到内存占用了17M多的内存,这个正是刚才说的,比如这个图的尺寸是3488 × 2616,所以就有3488 × 2616个像素点,使用RGB_565的时候,每个像素点用2个字节存储。3488 × 2616 x 2正好就是17M多。
加载大图片的通常做法是,先通过设置Options.inJustDecodeBounds属性为true,这样decode的时候只会decode图片尺寸信息,通过Options.outHeight和outWidth取得。然后和希望的最大宽高值计算出inSampleSize。
The sample size is the number of pixels in either dimension that correspond to a single pixel in the decoded bitmap. For example, inSampleSize == 4 returns an image that is 1/4 the width/height of the original, and 1/16 the number of pixels.
也就是说横向和纵向用sample size个点表示一个点。例如,inSampleSize == 4,返回一个原来宽高的1/4的图片,有原来像素数的1/16。
另外,不同机型的Heap最大大小是不一样的,一些机型
Heap size limits
– G1: 16MB
– Droid: 24MB
– Nexus One: 32MB
– Xoom: 48MB
具体手机可以通过ActivityManager.getMemoryClass()来获取Heap大小。Heap大小是动态分配的,有一个最小的初始值,然后会随内存分配动态增长,这是和标准jvm一样的。
这个值也可以通过更改/system/build.prop文件中的dalvik.vm.heapsize来改变。
对于GC的方式也是有区别的:
o Pre-Gingerbread GC:
– Stop-the-world
– Full heap collection
– Pause times often & 100ms
o Gingerbread and beyond:
– Concurrent (mostly)
– Partial collections
– Pause times usually & 5ms
最后,分析内存情况的话可以使用DDMS,dump出内存使用的情况,然后使用Eclipse Memory Analyzer (MAT)来分析内存使用情况。
Google IO 11有个Session是“memory_management_for_android_apps”部分参考了这个Session的内容。问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
我从网上下载了一张图片。
private void downloadPost()
HttpURLConnection conn =
URL url = new URL(IMAGE_URL);
conn = (HttpURLConnection) url.openConnection();
if (conn.getResponseCode() == HttpStatus.SC_OK)
InputStream is = conn.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(is);
Message msg = new Message();
msg.what = 1;
handler.sendMessage(msg);
catch (Exception e)
e.printStackTrace();
传给Handler处理的时候,如果设置了bitmap的回收,则imageview.setImageBitmap(bitmap);没有显示图片,但是注视掉以后就显示了,是我回收的地方不对吗?
public void handleMessage(Message msg)
super.handleMessage(msg);
switch (msg.what)
Bitmap bitmap = (Bitmap) msg.
imageview.setImageBitmap(bitmap);
if (bitmap != null && !bitmap.isRecycled())
bitmap.recycle();
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
怎么看着好奇怪啊,好像图片异步加载+三级缓存;bitmap回收的时机的确不对;首先setImageBitmap()这个方法只是对bitmap的引用,并没有重新创建bitmap,recycle()之后,bitmap从内存清空,当然显示不出图片。在handler中如果非要回收,那可以bitmap = null销毁引用,然后等待GC回收(并不知道有没有卵用);建议在转场的时候进行释放,比如Activity的onDestory()方法里。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
你在哪里都不应该回收啊.回收了之后显示不出来不是正常的?
The bitmap is marked as "dead", meaning it will throw an exception if getPixels() or setPixels() is called, and will draw nothing.
同步到新浪微博
分享到微博?
Hi,欢迎来到 SegmentFault 技术社区!⊙▽⊙ 在这里,你可以提出编程相关的疑惑,关注感兴趣的问题,对认可的回答投赞同票;大家会帮你解决编程的问题,和你探讨技术更新,为你的回答投上赞同票。
明天提醒我
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:}

我要回帖

更多关于 android url转bitmap 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信