android UI 优化系列之 创建RGB565的缓存

    技术2022-05-20  65

    转自http://www.bangchui.org/read.php?tid=8458

     

     

    关于如何优化activity的启动速度, view 的绘制速度, 可参考这个sdk里的文档。 android-sdk-windows-1.5_r1/docs/resources/articles/window-bg-speed.html。 看完后你就知道 android:windowBackground 太重要了,影响到绘制效率。 这里要说的是另外一点, 不是这个windowBackground 。 android 为了提高滚动等各方面的绘制速度,可以为每一个view建立一个缓存,使用 View.buildDrawingCache为自己的view 建立相应的缓存, 这个所谓的缓存,实际上就是一个Bitmap对象。只是 这个 bitmap 对象可以有多种格式而已,如      Bitmap.Config.ARGB_8888;      Bitmap.Config.ARGB_4444;      Bitmap.Config.ARGB_8888;      Bitmap.Config.ARGB_8888;      Bitmap.Config.RGB_565;    默认的格式是Bitmap.Config.ARGB_8888.,但大多数嵌入式设备使用的显示格式都是Bitmap.Config.RGB_565. 对于后者, 并没有 alpha 值,所以绘制的时候不需要计算alpha合成,速递当让快些。其次,RGB_565可以直接使用优化了的memcopy函数,效率相对高出许多。   所以, 在用buildDrawingCache建立缓存时, 可以使用RGB_565格式。但是如何制定这个格式呢 ?buildDrawingCache有两个版本,     buildDrawingCache(boolean) buildDrawingCache() 。并没有任何参数可以设置rgb格式,看看源码先: public void buildDrawingCache(boolean autoScale) {         if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || (autoScale ?                 (mDrawingCache == null || mDrawingCache.get() == null) :                 (mUnscaledDrawingCache == null || mUnscaledDrawingCache.get() == null))) {             if (ViewDebug.TRACE_HIERARCHY) {                 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.BUILD_CACHE);             }             if (Config.DEBUG && ViewDebug.profileDrawing) {                 EventLog.writeEvent(60002, hashCode());             }             int width = mRight - mLeft;             int height = mBottom - mTop;             final AttachInfo attachInfo = mAttachInfo;             final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;             if (autoScale && scalingRequired) {                 width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);                 height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);             }             final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;              final boolean opaque = drawingCacheBackgroundColor != 0 ||                 (mBGDrawable != null && mBGDrawable.getOpacity() == PixelFormat.OPAQUE);             if (width <= 0 || height <= 0 ||                     (width * height * (opaque ? 2 : 4) > // Projected bitmap size in bytes                             ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize())) {                 destroyDrawingCache();                 return;             }             boolean clear = true;             Bitmap bitmap = autoScale ? (mDrawingCache == null ? null : mDrawingCache.get()) :                     (mUnscaledDrawingCache == null ? null : mUnscaledDrawingCache.get());             if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {                 Bitmap.Config quality;                 if (!opaque) {                     switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {                         case DRAWING_CACHE_QUALITY_AUTO:                             quality = Bitmap.Config.ARGB_8888;                             break;                         case DRAWING_CACHE_QUALITY_LOW:                             quality = Bitmap.Config.ARGB_4444;                             break;                         case DRAWING_CACHE_QUALITY_HIGH:                             quality = Bitmap.Config.ARGB_8888;                             break;                         default:                             quality = Bitmap.Config.ARGB_8888;                             break;                     }                 } else {                     quality = Bitmap.Config.RGB_565;                 }                 // Try to cleanup memory                 if (bitmap != null) bitmap.recycle();                 try {                     bitmap = Bitmap.createBitmap(width, height, quality);                     bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);                     if (autoScale) {                         mDrawingCache = new SoftReference<Bitmap>(bitmap);                     } else {                         mUnscaledDrawingCache = new SoftReference<Bitmap>(bitmap);                     }                 } catch (OutOfMemoryError e) {                     // If there is not enough memory to create the bitmap cache, just                     // ignore the issue as bitmap caches are not required to draw the                     // view hierarchy                     if (autoScale) {                         mDrawingCache = null;                     } else {                         mUnscaledDrawingCache = null;                     }                     return;                 }                 clear = drawingCacheBackgroundColor != 0;             }             Canvas canvas;             if (attachInfo != null) {                 canvas = attachInfo.mCanvas;                 if (canvas == null) {                     canvas = new Canvas();                 }                 canvas.setBitmap(bitmap);                 // Temporarily clobber the cached Canvas in case one of our children                 // is also using a drawing cache. Without this, the children would                 // steal the canvas by attaching their own bitmap to it and bad, bad                 // thing would happen (invisible views, corrupted drawings, etc.)                 attachInfo.mCanvas = null;             } else {                 // This case should hopefully never or seldom happen                 canvas = new Canvas(bitmap);             }             if (clear) {                 bitmap.eraseColor(drawingCacheBackgroundColor);             }             computeScroll();             final int restoreCount = canvas.save();             if (autoScale && scalingRequired) {                 final float scale = attachInfo.mApplicationScale;                 canvas.scale(scale, scale);             }             canvas.translate(-mScrollX, -mScrollY);             mPrivateFlags |= DRAWN;             // Fast path for layouts with no backgrounds             if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {                 if (ViewDebug.TRACE_HIERARCHY) {                     ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);                 }                 mPrivateFlags &= ~DIRTY_MASK;                 dispatchDraw(canvas);             } else {                 draw(canvas);             }             canvas.restoreToCount(restoreCount);             if (attachInfo != null) {                 // Restore the cached Canvas for our siblings                 attachInfo.mCanvas = canvas;             }             mPrivateFlags |= DRAWING_CACHE_VALID;         }     } 看完后明白了,至少跟两个因素有关 drawingCacheBackgroundColor 和 mBGDrawable. 用setDrawingCacheBackgroundColor(0xffff0000)设置为 非默认颜色后,建立的缓存就是rgb565了,可以用下列方法验证一下: final Bitmap cache = mContent.getDrawingCache();             if (cache != null) {              Config cfg = cache.getConfig();              Log.d(TAG, "----------------------- cache.getConfig() = " + cfg);         }


    最新回复(0)