關於android ui的優化 view 的繪製速度

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

        }



更多UI優化請參考 http://www.bangchui.org/read.php?tid=16

發佈了23 篇原創文章 · 獲贊 6 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章