bitmtap什么时候recycle

bitmap在调用recycle之后 会不会马上回收图片?怎么回收?

先看源码

  1. public void recycle() {
  2.         if (!mRecycled) {
  3.             mBuffer = null;
  4.             nativeRecycle(mNativeBitmap);
  5.             mNinePatchChunk = null;
  6.             mRecycled = true;
  7.         }
  8.     }

这个方法首先将这个Bitmap的引用置为null,然后调用了nativeRecycle(mNativeBitMap)方法,这个方法很明显是个JNI调用,会调用底层的c或者c++代码就可以做到对该内存的立即回收,而不需要等待那不确定啥时候会执行的GC来回收了。

 public void recycle ()
Since: API Level 1

      Free the native object associated with this bitmap, and clear the reference to the pixel data. This will not free the pixel data synchronously; 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.

 释放本地的对象对bitmap的关联。清除对本地对像素的引用。但这个像素不会马上被回收。如果没有其他的引用像素,将会被gc回收。这个bitmap被标识成dead,意味着如果这个时候去调用bitmap的getPixels() 或者setPixels()将会抛会异常。并且什么都显示不出来。这个操作是不可逆的,如果调用recycle。所以你要确定以后不在用这个bitmap之后,你在调用recycle()。这是一个改进的调用,通常是不要调用,通常gc将释放这个内存,但没有引用指向这个内存。

 

看一段代码

public void monitorBitmap() {
          Bitmap src = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888);
          ...
          src.recycle();
     }

 

sample code的monitorBitmap()中只做了两件事情:
1. new一个Bitmap,
2. 回收它(recycle()).

 

 


首先,trace create Bitmap object 的过程,
1. createBitmap(int width, int height, Config config); [Bitmap.java]
2. nativeCreate(int[] colors, int offset,  int stride, int width, int height, int nativeConfig, boolean mutable); [Bitmap.java]
---JNI------------------------------------------------------
3. Bitmap_creator(JNIEnv* env, jobject, jintArray jColors, int offset, int stride, int width, int height, SkBitmap::Config config, jboolean isMutable); [Bitmap.cpp]
4. GraphicsJNI::setJavaPixelRef(env, &bitmap, NULL, true); [Graphics.cpp]
5.1. JNIEnv::CallBooleanMethod(gVMRuntime_singleton, gVMRuntime_trackExternalAllocationMethodID, jsize); [Graphics.cpp]
5.2. void* addr = sk_malloc_flags(size, 0); [Graphics.cpp]
5.3. SkPixelRef* pr = new AndroidPixelRef(env, addr, size, ctable, reportSizeToVM); [Graphics.cpp]
5.4. bitmap->setPixelRef(pr)->unref(); [Graphics.cpp]


在5.1., JVM记录Bitmap的size,并且跟踪它.

   5.2.,5.3. malloc pixel buffer同时放入SkPixelRef object中以方便控管. SkPixelRef继承SkRefCnt,因此使用了reference count的技巧,可以检查有多少個object引用到它.

   5.4. 将SkPixelRef放入SkBitmap, 同时將先前Bitmap object内部所持有的SkPixelRef object unref().

 


最后,来看Bitmap object被recycle()時,做了操作

1. recycle(); [Bitmap.java]
2. nativeRecycle(int nativeBitmap); [Bitmap.java]
---JNI------------------------------------------------------
3. Bitmap_recycle(JNIEnv* env, jobject, SkBitmap* bitmap); [Bitmap.cpp]
4. SkBitmap::setPixels(NULL, NULL); [SkBitmap.cpp]
5. SkBitmap::freePixels(); [SkBitmap.cpp]
6. AndroidPixelRef::unref(); [Graphics.cpp]
7. AndroidPixelRef::~AndroidPixelRef(); [Graphics.cpp]
8. JNIEnv::CallVoidMethod(gVMRuntime_singleton, gVMRuntime_trackExternalFreeMethodID, jsize); [Graphics.cpp]
在步骤8, JVM移除先前所记录的pixel buffer size的记录.
由上面的范例中,我們可以得知JVM是如何记录跟踪Bitmap size的大小.

 

Dalvik:

进行数据统计,然后调用GC。其实还是全部靠Bitmap自己管理。

posted on 2013-04-02 10:10  mingfeng002  阅读(595)  评论(0编辑  收藏  举报