前面了解了什么是SurfaceView和SurfaceView的簡單使用,現(xiàn)在要學(xué)習(xí)怎么在SurfaceView中畫畫。
class OurView extends SurfaceView implements Runnable{
SurfaceHolder holder;
...
public void OurView(Context context){
holder = getHolder();
}
public void run(){
while(isRunning){
//判斷Surface是否已經(jīng)準(zhǔn)備好
if(!holder.getSurface().isValid()){
continue;
}
Canvas canvas = holder.lockCanvas();
//draw somethings...
holder.unlockCanvasAndPost(canvas);
}
}
...
}
在上面的代碼中,有一個類叫SurfaceHolder,這個又是什么東西呢?
SurfaceHolder在android.view包下,是一個接口,“一個為某些類提供一塊Surface的抽象接口,你可以通過他控制Surface的尺寸和格式,編輯Surface的像素,監(jiān)控Surface的變化,這個接口通常用于SurfaceView類,當(dāng)不止一個線程訪問SurfaceView時,你需要格外小心使用lockCanvas()和Callback.surfaceCreated()”
上面提到了lockCanvas(),在前面介紹什么是SurfaceView中有提到這個方法,不過是在Surface類中,那么,SurfaceHolder中也有這個方法,他們之間有什么關(guān)系呢,去SurfaceHolder看一下源碼:
mSurfaceHolder是一個屬性,再去看看SurfaceHolder的lockCanvas()方法
繼續(xù)看internalLockCanvas();
該方法要求傳入一個矩形區(qū)域,返回一個Canvas對象,看看里面做了什么
首先調(diào)用mSurfaceLock.lock(),mSurfaceLock是一個ReentrantLock,什么是ReentrantLock?
首先,該類是在java.util.concurrent.locks包下,由此可見,它是一個工具類,同時也是跟鎖有關(guān),在java中,synchronized同步鎖是我們常常見到的,那么ReentrantLock是什么鎖呢?
ReentrantLock是一個可重入互斥鎖,相較于Synchronized,它支持類似鎖投票,定時鎖等候和可中斷鎖等候,同時,性能更高。
也就是說,mSurfaceLock.lock()是為了保證internalLockCanvas的原子性。
再看internalLockCanvas();
Canvas c = null;
if (!mDrawingStopped && mWindow != null) {
try {
c = mSurface.lockCanvas(dirty);
} catch (Exception e) {
Log.e(LOG_TAG, "Exception locking surface", e);
}
}
這段代碼中,有兩個未知屬性,mDrawingStoped和mWindow:
mDrawingStoped:Boolean,主要是記錄是否需要繪制的標(biāo)記,如果UNVISIABLE了,就是true,否則為false;
mWindow對應(yīng)的類MyWindow是個什么東東,MyWindow是繼承自BaseIWindow類,重寫了resized方法,
MyWindow resized方法
resized中主要是想mHandler發(fā)送消息,重繪窗口,mHandler收到消息后,調(diào)用updateWindow方法更新窗口。
緊接著,執(zhí)行mSurface.lockCanvas(dirty)方法,前面介紹個,改方法會返回一個Canvas用于在dirty這個矩形區(qū)域繪制
如果dirty為null,則表示整個窗口。
由此可見holder.lockCanvas(),最后實際執(zhí)行的還是Surface.lockCanvas(dirty)方法,得到Canvas后,我們便可以利用Canvas開始繪制我們想要的任何東西。
記得在繪制完成后,調(diào)用holder.unlockCanvasAndPost(canvas)將繪制的內(nèi)容發(fā)送給Surface。