1、什麼是Surfacejava
簡單的說Surface對應了一塊屏幕緩衝區,每一個window對應一個Surface,任何View都要畫在Surface的Canvas上(後面有緣由解釋)。傳統的view共享一塊屏幕緩衝區,全部的繪製必須在UI線程中進行。android
在SDK的文檔中,對Surface的描述是這樣的:「Handle onto a raw buffer that is being managed by the screen compositor」,翻譯成中文就是「由屏幕顯示內容合成器(screen compositor)所管理的原始緩衝區的句柄」,這句話包括下面兩個意思:程序員
一、經過Surface(由於Surface是句柄)就能夠得到原生緩衝器以及其中的內容。就像在C++語言中,能夠經過一個文件的句柄,就能夠得到文件的內容同樣。canvas
二、 原始緩衝區(a raw buffer)是用於保存當前窗口的像素數據的。設計模式
引申地,能夠認爲Android中的Surface就是一個用來畫圖形(graphics)或圖像(image)的地方。app
根據Java方面的常規知識,咱們知道一般畫圖是在一個Canvas對象上面進行的,由此,能夠推知一個Surface對象中應該包含有一個Canvas(畫布)對象。所以,在前面說起的兩個意思的基礎上,能夠再加上一條:ide
三、Surface中有一個Canvas成員,專門用於畫圖的。this
由以上的歸納,咱們總結以下:Surface中的Canvas成員,是專門用於供程序員畫圖的場所,就像黑板同樣;其中的原始緩衝區是用來保存數據的地方;Surface自己的做用相似一個句柄,獲得了這個句柄就能夠獲得其中的Canvas、原始緩衝區以及其它方面的內容。spa
Surface是用來管理數據的。(句柄).net
2、什麼是SurfaceView
說SurfaceView是一個View也許不夠嚴謹,然而從定義中pubilc classSurfaceView extends View{.....}顯示SurfaceView確實是派生自View,可是SurfaceView卻有本身的Surface,請看SurfaceView的源碼:
[java] view plain copy
<span style="font-size:14px;color:#333333;"> if (mWindow == null) {
mWindow = new MyWindow(this);
mLayout.type = mWindowType;
mLayout.gravity = Gravity.LEFT|Gravity.TOP;
mSession.addWithoutInputChannel(mWindow, mWindow.mSeq, mLayout,
mVisible ? VISIBLE : GONE, mContentInsets);
} </span>
很明顯,每一個SurfaceView建立的時候都會建立一個MyWindow,new MyWindow(this)中的this正是SurfaceView自身,所以將SurfaceView和window綁定在一塊兒,由第一部分咱們知道,一個window對應一個Surface,所以SurfaceView也就內嵌了一個本身的Surface,能夠認爲SurfaceView是用來控制Surface中View的位置和尺寸的。
SurfaceView就是展現Surface中數據的地方,同時能夠認爲SurfaceView是用來控制Surface中View的位置和尺寸的。
你們都知道,傳統View及其派生類的更新只能在UI線程,然而UI線程還同時處理其餘交互邏輯,這就沒法保證View更新的速度和幀率了,而SurfaceView能夠用獨立的線程進行繪製,所以能夠提供更高的幀率,例如遊戲,攝像頭取景等場景就比較適合SurfaceView來實現。
3、什麼是SurfaceHolder
SurfaceHolder是一個接口,其做用就像一個關於Surface的監聽器,提供訪問和控制SurfaceView內嵌的Surface 相關的方法。它經過三個回調方法,讓咱們能夠感知到Surface的建立、銷燬或者改變。
在SurfaceView中有一個方法getHolder,能夠很方便地得到SurfaceView內嵌的Surface所對應的監聽器接口SurfaceHolder(有點拗口吧)。
除下面將要提到的SurfaceHolder.Callback外,SurfaceHolder還提供了不少重要的方法,其中最重要的就是:
一、abstract void addCallback(SurfaceHolder.Callbackcallback):爲SurfaceHolder添加一個SurfaceHolder.Callback回調接口。
二、abstract Canvas lockCanvas():獲取一個Canvas對象,並鎖定之。所獲得的Canvas對象,其實就是Surface中一個成員。
三、abstract Canvas lockCanvas(Rect dirty):同上。但只鎖定dirty所指定的矩形區域,所以效率更高。
四、abstract void unlockCanvasAndPost(Canvas canvas):當修改Surface中的數據完成後,釋放同步鎖,並提交改變,而後將新的數據進行展現,同時Surface中相關數據會被丟失。
二、三、4中的同步鎖機制的目的,就是爲了在繪製的過程當中,Surface中的數據不會被改變。lockCanvas是爲了防止同一時刻多個線程對同一canvas寫入。
總結:從設計模式的高度來看,Surface、SurfaceView和SurfaceHolder實質上就是廣爲人知的MVC,即Model-View-Controller。Model就是模型的意思,或者說是數據模型,或者更簡單地說就是數據,也就是這裏的Surface;View即視圖,表明用戶交互界面,也就是這裏的SurfaceView;SurfaceHolder很明顯能夠理解爲MVC中的Controller(控制器)。
4、什麼是SurfaceHolder.Callback
SurfaceHolder.Callback主要是當底層的Surface被建立、銷燬或者改變時提供回調通知,因爲繪製必須在Surface被建立後才能進行,所以SurfaceHolder.Callback中的surfaceCreated 和surfaceDestroyed 就成了繪圖處理代碼的邊界。
SurfaceHolder.Callback中定義了三個接口方法:
一、abstract void surfaceChanged(SurfaceHolder holder, int format, int width, int height):當surface發生任何結構性的變化時(格式或者大小),該方法就會被當即調用。
二、abstract void surfaceCreated(SurfaceHolder holder):當surface對象建立後,該方法就會被當即調用。
三、abstract void surfaceDestroyed(SurfaceHolder holder):當surface對象在將要銷燬前,該方法會被當即調用。
5、實例演示
下面,咱們經過一個很是簡單例子來實際感覺一下,請留意代碼中的註釋:
一、在Eclipse中建立一個android Project項目TestSurfaceView,並選擇生成缺省的Activity TestSurfaceViewActivity
二、建立一個繪製線程以下:
[java] view plain copy
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
importandroid.view.SurfaceHolder;
// 繪製線程
public class MyThread extends Thread
{
private SurfaceHolder holder;
private boolean run;
public MyThread(SurfaceHolder holder)
{
this.holder = holder;
run = true;
}
@Override
public void run()
{
int counter = 0;
Canvas canvas = null;
while(run)
{
// 具體繪製工做
try
{
// 獲取Canvas對象,並鎖定之
canvas= holder.lockCanvas();
// 設定Canvas對象的背景顏色
canvas.drawColor(Color.WHITE);
// 建立畫筆
Paint p = new Paint();
// 設置畫筆顏色
p.setColor(Color.BLACK);
// 設置文字大小
p.setTextSize(30);
// 建立一個Rect對象rect
Rect rect = new Rect(100, 50, 380, 330);
// 在canvas上繪製rect
canvas.drawRect(rect,p);
// 在canvas上顯示時間
canvas.drawText("Interval = " + (counter++) + " seconds.", 100, 410, p);
Thread.sleep(1000);
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
if(canvas != null)
{
// 解除鎖定,並提交修改內容
holder.unlockCanvasAndPost(canvas);
}
}
}
}
public boolean isRun()
{
return run;
}
public void setRun(boolean run)
{
this.run = run;
}
}
三、自定義一個SurfaceView類以下:
[java] view plain copy
import android.content.Context;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class MySurfaceView extends SurfaceView<span style="font-family:Arial;"> </span>implements<span style="font-family:Arial;"> </span>SurfaceHolder.Callback
{
private SurfaceHolder holder;
private MyThread myThread;
public MySurfaceView(Context context)
{
super(context);
// 經過SurfaceView得到SurfaceHolder對象
holder = getHolder();
// 爲holder添加回調結構SurfaceHolder.Callback
holder.addCallback(this);
// 建立一個繪製線程,將holder對象做爲參數傳入,這樣在繪製線程中就能夠得到holder
// 對象,進而在繪製線程中能夠經過holder對象得到Canvas對象,並在Canvas上進行繪製
myThread = new MyThread(holder);
}
// 實現SurfaceHolder.Callback接口中的三個方法,都是在主線程中調用,而不是在繪製線程中調用的
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
}
@Override
public void surfaceCreated(SurfaceHolder holder)
{
// 啓動線程。當這個方法調用時,說明Surface已經有效了
myThread.setRun(true);
myThread.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder)
{
// 結束線程。當這個方法調用時,說明Surface即將要被銷燬了
myThread.setRun(false);
}
}
四、修改TestSurfaceViewActivity.java代碼,使之以下:
[java] view plain copy
import android.app.Activity;
import android.os.Bundle;
public class TestSurfaceViewActivity extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);
setContentView(new MySurfaceView(this));
}
}
總結:從設計模式的高度來看,Surface、SurfaceView和SurfaceHolder實質上就是廣爲人知的MVC,即Model-View-Controller。Model就是模型的意思,或者說是數據模型,或者更簡單地說就是數據,也就是這裏的Surface;View即視圖,表明用戶交互界面,也就是這裏的SurfaceView;SurfaceHolder很明顯能夠理解爲MVC中的Controller(控制器)。