原文:Android圖形系統之Surface、SurfaceView、SurfaceHolder及SurfaceHolder.Callback之間的聯系
Surface是原始圖像緩沖區(raw buffer)的一個句柄,而原始圖像緩沖區是由屏幕圖像合成器(screen compositor)管理的。
Surface本身的作用類似一個句柄,得到了這個句柄就可以得到其中的Canvas、原生緩沖器以及其它方面的內容。
通過SurfaceHolder這個接口去訪問Surface,而執行getHolder()方法可以得到SurfaceHolder接口。當SurfaceView的窗口可見時,Surface就會被創建,當SurfaceView窗口隱藏時,Surface就會被銷毀。
SurfaceView提供了一個運行在渲染線程的surface,若要更新屏幕,需要了解以下線程知識。
- 所有SurfaceView 和 SurfaceHolder.Callback的方法都應該在主線程(UI線程)里面調用,應該要確保渲染進程所訪問變量的同步性。
- 必須確保只有當Surface有效的時候,(也就是當Surface的生命周期在SurfaceHolder.Callback.surfaceCreated() 和SurfaceHolder.Callback.surfaceDestroyed()之間)才能讓渲染進程訪問。
SurfaceView與Surface的聯系就是,Surface是管理顯示內容的數據(implementsParcelable),包括存儲於數據的交換。而SurfaceView就是把這些數據顯示出來到屏幕上面。
SurfaceHolder是控制surface的一個抽象接口,你可以通過SurfaceHolder來控制surface的尺寸和格式,或者修改surface的像素,監視surface的變化等等,SurfaceHolder是SurfaceView的典型接口。
與直接控制SurfaceView來修改surface不同,使用SurfaceHolder來修改surface時,需要注意lockCanvas() 和Callback.surfaceCreated().這兩個方法。
SurfaceHolder控制surface的流程所使用的幾個方法。
3.1、abstract void addCallback(SurfaceHolder.Callback callback) |
SurfaceHolder.Callback是監聽surface改變的一個接口
- public abstract voidsurfaceChanged(SurfaceHolder holder, int format, int width, int height)
holder The SurfaceHolder whose surface has changed.
format The new PixelFormat of the surface.
width The new width of the surface.
height The new height of the surfa //surface發生改變時被調用
2. public abstract voidsurfaceCreated(SurfaceHolder holder)
Parameters holder The SurfaceHolder whose surface is being created
//在surface創建時被調用,一般在這個方法里面開啟渲染屏幕的線程。
3. public abstract voidsurfaceDestroyed(SurfaceHolder holder)
Parameters holder The SurfaceHolder whose surface is being destroyed.
//銷毀時被調用,一般在這個方法里將渲染的線程停止。
Demo:
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new MyView(this)); } class MyView extends SurfaceView implements SurfaceHolder.Callback, Runnable { SurfaceHolder holder = null; Paint paint; public MyView(Context context) { super(context); holder = getHolder(); holder.addCallback(this); paint = new Paint(Paint.ANTI_ALIAS_FLAG); // 創建畫筆 paint.setColor(Color.RED); // 設置畫筆顏色 this.setFocusable(true); } @Override public void surfaceCreated(SurfaceHolder holder) { Thread t = new Thread(this); t.start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { isRunning = false; } @Override protected void onDraw(Canvas canvas) { canvas = holder.lockCanvas(); canvas.drawColor(Color.BLACK); canvas.drawCircle(x, y, 10, paint); holder.unlockCanvasAndPost(canvas); } private void paint(Paint paint) { Canvas canvas = holder.lockCanvas(); // 鎖定畫布,得到Canvas對象 canvas.drawColor(Color.WHITE); // 設定Canvas對象的背景顏色 canvas.drawCircle(x, y, 10, paint); // 在畫布上畫圓 holder.unlockCanvasAndPost(canvas); // 解除鎖定,並提交修改內容,更新屏幕 } boolean isRunning = true; @Override public void run() { while (isRunning) { // onDraw(null); paint(paint); move(); try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } } private int x, y; private void move() { x += 2; y += 2; } } }