關於如何最佳化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); |