渲染性能 Android UI的工作分兩階段: 1.在UI線程Record View#draw 2.在RenderThread線程DrawFrame(RenderThread:使用GPU資源的線程) 第一階段隨著View的invalidated在draw(Canvas)中進行 第二階段native ...
渲染性能
Android UI的工作分兩階段:
1.在UI線程Record View#draw
2.在RenderThread線程DrawFrame(RenderThread:使用GPU資源的線程)
第一階段隨著View的invalidated在draw(Canvas)中進行
第二階段native RenderThread基於Record View#draw步驟所產生的數據內容而進行相應的處理。
渲染性能:UI線程
如果Record View#draw占用時間長,比如在UI線程繪製bitmap。當然,這種直接在UI線程繪製bitmap的方式應該避免使用。
示例1:在主線程完成bitmap繪製,並顯示圓角頭像自定義控制項,onDraw代碼實現可能如:
Canvas bitmapCanvas = new Canvas(roundedOutputBitmap); Paint paint = new Paint(); paint.setAntiAlias(true); bitmapCanvas.drawRoundRect(0, 0, roundedOutputBitmap.getWidth(), roundedOutputBitmap.getHeight(), 30, 30, paint); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); bitmapCanvas.drawBitmap(sourceBitmap, 0, 0, paint); bitmapCanvas.setBitmap(null); canvas.drawBitmap(roundedOutputBitmap, 0, 0, null);
如果你現在是用這種方式實現其它自定義控制項bitmap的繪製,假設sourceBitmap是一個很大的點陣圖,哪怕是緩存,載入進來會出現明顯的卡頓現象,所以用後臺線程完成這個工作。
示例2:.有時自定義控制項需要在設置bitmap的時候,才顯示bitmap,代碼如下:
void setBitmap(Bitmap bitmap) { mBitmap = bitmap; invalidate(); } void onDraw(Canvas canvas) { canvas.drawBitmap(mBitmap, null); }
可以考慮用下麵的代碼替換:
void setBitmap(Bitmap bitmap) { mShaderPaint.setShader( new BitmapShader(bitmap, TileMode.CLAMP, TileMode.CLAMP)); invalidate(); } void onDraw(Canvas canvas) { canvas.drawRoundRect(0, 0, mWidth, mHeight, 20, 20, mShaderPaint); }
這樣可以給bitmap數據源起到保護的作用,避免bitmap中間因為其他的修改(如在bitmap數據源頭添加漸變效果或者顏色過濾)而導致bitmap的數據源被修改。
渲染性能:RenderThread
有些放在onDraw(canvas)中的代碼套路或許很容易想到,但卻會在RenderThread觸發頻繁的運算。
示例
canvas.save();
canvas.clipPath(mCirclePath);
canvas.drawBitmap(mBitmap);
canvas.restore();
clipPath(Path)會觸發很多裁剪工作,應該儘量少用。可以的話,考慮用下麵這種方式替換:
mPaint.setShader(new BitmapShader(mBitmap, TileMode.CLAMP, TileMode.CLAMP)); canvas.drawPath(mCirclePath, mPaint);
Android把bitmaps作為OpenGL的紋理來顯示,第一次在一幀中顯示bitmap時,它就會被上傳到GPU上。如下圖Systrace所示的Upload width x heigth Texture。雖然它只需要若幹毫秒,但還是很有必要讓GPU去顯示圖片的。
如果這個過程占用很長的時間,可以先查看width和height的值。確保顯示的bitmap沒有比屏幕所需要展示點陣圖的區域還大。如果width和height的值比展示bitmap的區域還大,那麼就會導致upload bitmap to GPU的時間以及記憶體的浪費。不過現在的圖片載入庫基本都實現了合適的尺寸載入點陣圖的功能。