練習:https://github.com/zhangbz/AndroidUIPorblems
查看過度繪制
在開發者選項中開啟"調試GPU過度繪制"
判斷標准
無色:沒有過度繪制,即只繪制了一次
藍色:一倍過度繪制
綠色:二倍過度繪制
淡紅色:三倍過度繪制
紅色:四倍或以上過度繪制
實踐
其中"This is test"四次或以上倍數過度繪制,其背景三倍,按鈕兩倍,按鈕中的文字三倍,背景一倍.
Mainactivity優化
首先分析布局文件,發現嵌套的LinearLayout設置了與父LinearLaytout相同的背景色,故刪除其背景色設置,效果如下
然后由於Android自帶的一些主題,window會被默認添加一個純色的背景,因為這個Activity的界面的背景占滿了整個屏幕,所以我們可以去掉該activity的默認繪制,在mainactivity的onCreate()方法里面修改代碼。
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); getWindow().setBackgroundDrawable(null);//新增代碼 //... }
效果如下:
至此,消除了該頁面三倍及以上過度繪制.
overdrawview優化
原實現方法如下,由於onDraw()方法中繪制的圖形存在覆蓋現象,因而導致了過度繪制
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int width = getWidth(); int height = getHeight(); mPaint.setColor(Color.GRAY); canvas.drawRect(0, 0, width, height, mPaint); mPaint.setColor(Color.CYAN); canvas.drawRect(0, height/4, width, height, mPaint); mPaint.setColor(Color.DKGRAY); canvas.drawRect(0, height/3, width, height, mPaint); mPaint.setColor(Color.LTGRAY); canvas.drawRect(0, height/2, width, height, mPaint); }
修改代碼,避免相互覆蓋
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int width = getWidth(); int height = getHeight(); mPaint.setColor(Color.GRAY); canvas.drawRect(0, 0, width, height/4, mPaint); mPaint.setColor(Color.CYAN); canvas.drawRect(0, height/4, width, height/3, mPaint); mPaint.setColor(Color.DKGRAY); canvas.drawRect(0, height/3, width, height/2, mPaint); mPaint.setColor(Color.LTGRAY); canvas.drawRect(0, height/2, width, height, mPaint); }
優化效果
busyondraw優化
點擊按鈕時會出現明顯的卡頓現象,從以下代碼中可以判斷,造成該問題的原因應該是onDraw()方法中的耗時操作
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); for (int i = 0; i < 1000; i++) { System.out.println("canvas = [" + canvas + "]" + i); } Paint paint = new Paint(); paint.setColor(Color.RED); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(4); int radius = Math.min(getWidth(), getHeight()) / 2; canvas.drawCircle(getWidth()/2, getHeight()/2, radius, paint); }
優化方案:將耗時操作移入到子線程中
new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 1000; i++) { System.out.println("canvas = [" + canvas + "]" + i); } } }).start();