Android-SurfaceView的總結

Android-SurfaceView的總結

緣由:

Android系統提供View進行繪圖處理,但是很多時候會顯得心有餘而力不足,比如當view繪圖進行大量的操作,容易使主線程阻塞,並且在logcat輸出···

"skipped 47 frames! the application may be doing much work in main thread"

這個當我在頁面進行大量的視圖動畫時,經常出現。

所以當你的View需要頻繁的刷新,或者刷新時數據處理量比較大時,建議使用SurfaceView。

View繪圖方式:

View是通過刷新來更新視圖。系統通過發送VSYnc信號來通知屏幕進行刷新,刷新頻率爲16ms,因此當你的View刷新時間超過16ms,就會出現卡頓。

View和surfaceView的比較:

1.view適用於主動進行畫面更新,而surfaceView適合被動進行更新。

2.view更新運行在主線程,容易造成主線程的阻塞,而surfaceView運行在新的子線程中。

3.VIew繪圖沒有使用雙緩衝機制,而surfaceView底層已經實現雙緩衝機制。

說明:雙緩衝機制--當要在指定View上繪製圖形時,不直接在View上繪製,而是先繪製到內存中的Bitmap圖片上,等到緩存的Bitmap 繪製好,以後,再將bitmap上的直接繪製View組件上。

surfaceView的使用:

1.繼承自SurfaceView,實現SurfaceHolder,CallBack,Runnable接口

2.並且重寫抽象方法

2.在xml文件中使用或者動態生成

實例代碼:

public class KillView extends SurfaceView  implements SurfaceHolder.Callback,Runnable{

private SurfaceHolder holder;
private Canvas canvas;
private boolean isDrawing;
private Paint paint;

public KillView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}

public KillView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}

public KillView(Context context) {
super(context);
init();
}

public void init(){
Log.e("TAG","init");
holder=getHolder();
holder.addCallback(this);
setFocusable(true);
setFocusableInTouchMode(true);
this.setKeepScreenOn(true);
}
Path path;

@Override
public void run() {
long start=System.currentTimeMillis();
   while (isDrawing){
        draw();
}
long end=System.currentTimeMillis();
Log.e("TAG","start="+start+" end="+end);
if(end-start<100){
try{

Thread.sleep(100-end+start);
}catch (Exception e){
e.printStackTrace();
}
}
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.e("TAG","create");
isDrawing=true;
path=new Path();
paint=new Paint();
paint.setColor(getResources().getColor(R.color.colorAccent));
new Thread(this).start();
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.e("TAG","change");
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.e("TAG","destroy");
isDrawing=false;


}

   public void draw(){
   try{
   canvas=holder.lockCanvas();
   canvas.drawCircle(getWidth()/2,getWidth()/2,100,paint);
   holder.unlockCanvasAndPost(canvas);
   canvas=holder.lockCanvas();
   canvas.drawColor(Color.WHITE);
   //canvas.drawPath(path,paint);
   canvas.drawArc(0,0,100,100,0,360,true,paint);
   }catch (Exception e){
  throw new IllegalArgumentException();
   }finally{
   if(holder!=null){
   holder.unlockCanvasAndPost(canvas);
   }
   }
        }
    }

代碼中方法說明:

1.getHolder()

surfaceView 一般與surfaceHolder結合使用,surfaceHolder用於向關聯的View繪圖 ,可通過getHolder方法獲得當前View的holder。

2.lockCanvas()

鎖定surfaceView對象,獲取surfaceView上的Canvas對象。

3.unlockCanvasANdPost()

當調用該方法時,之前繪製的內容還在內存中,當下次lockCanvas()時,可能會覆蓋之前的內容,因此如果想要持久化繪製內容,添加以下代碼:

holder.lockcanvas(new Rect(0,0,0,0);
holder.unlockcanvasAndPost(canvas);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章