這里以照相機camera功能的實現來解釋surface,surfaceview,sufaceholder以及surface客戶端(本例子中指的是camera)的關系,surface及其client(客戶端,本例子中指的是camera)之間的紐帶就是surfaceholder,它控制着surface及其client(客戶端,本例子中指的是camera)之間的連接or斷開,surfaceView座位視圖層級結構層面的組件,可以認為是它承載了surface,而surface是實際用來接收圖像原始像素繪制的緩沖區。
當含有surfaceView的試圖層級結構被放到屏幕上時surfaceCreated被調用,此時surfaceholder對surface及其客戶端進行關聯;
當surfaceView從屏幕上移除時調用surfaceDestroyed方法,也就意味着surface被銷毀,surfaceholder斷開surface及其客戶端的聯系;
當surface首次出現在屏幕上調用surfaceChanged方法,通過傳入的參數,可以告訴客戶端surface的像素格式以及surface的寬度和高度,告知客戶端有多大的繪制區域可以使用。
具體的看一下例子:(這里只是截取了有關surface,surfaceview,sufaceholder以及surface客戶端(本例子中指的是camera)的部分代碼,相機功能的具體實現代碼(camera.takePicture(Camera.ShutterCallback shutter,Camera.PictureCallback raw,Camera.PictureCallback jpeg)及其相關接口實現)沒有放出來,對於相機功能實現有興趣或有疑問的盆友可以留下郵箱),代碼中的mCamera是一個Camera對象。
1 mSurfaceView=(SurfaceView)view.findViewById(R.id.crime_camera_surface); 2 //surfaceholder 是我們與surface(實際承載圖像原始像素的緩沖區)對象聯系的紐帶 3 //實際上,surfaceholder是作為surface與surface的客戶端之間的紐帶的,因為要保證surface不存在時沒有任何內容要在他上面進行 4 //繪制,所以需要一個“中間人”(surfaceholder)進行協調他們之間的關系。當surface創建完成時,surfaceholder鏈接客戶端與 5 //surface保證他們進行交互,當surface銷毀之后,surfaceholder斷開surface及其客戶端的聯系。 6 SurfaceHolder holder=mSurfaceView.getHolder(); 7 holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 8 //SurfaceHolder.Callback()用於監聽surface的生命周期 9 holder.addCallback(new SurfaceHolder.Callback() { 10 //surfaceView從屏幕上移除時調用此方法,也就意味着surface被銷毀,surfaceholder斷開surface及其客戶端的聯系。 11 @Override 12 public void surfaceDestroyed(SurfaceHolder holder) { 13 // TODO Auto-generated method stub 14 if(mCamera!=null){ 15 //surface此時已經被銷毀,通過stopPreview方法停止camera在surface上的繪制操作 16 mCamera.stopPreview(); 17 } 18 } 19 //當含有surfaceView的試圖層級結構被放到屏幕上時surfaceCreated被調用,此時surfaceholder對surface及其客戶端進行關聯 20 @Override 21 public void surfaceCreated(SurfaceHolder holder) { 22 // TODO Auto-generated method stub 23 try{ 24 if(mCamera!=null){ 25 //通過setPrevireDisplay鏈接camera和surface 26 mCamera.setPreviewDisplay(holder); 27 } 28 }catch(IOException e){ 29 Log.e(TAG, "Setting up preview display failed", e); 30 } 31 } 32 //surface首次出現在屏幕上調用這個方法,通過傳入的參數,可以告訴客戶端surface的像素格式以及surface的寬度和高度, 33 //告知客戶端有多大的繪制區域可以使用。 34 @Override 35 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 36 // TODO Auto-generated method stub 37 if(mCamera==null){ 38 return; 39 } 40 Camera.Parameters parameters=mCamera.getParameters(); 41 Size size=getBestSupportedSize(parameters.getSupportedPreviewSizes(), width, height); 42 parameters.setPreviewSize(size.width, size.height); 43 size=getBestSupportedSize(parameters.getSupportedPictureSizes(), width, height); 44 parameters.setPictureSize(size.width, size.height); 45 mCamera.setParameters(parameters); 46 try{ 47 //通過startPreview方法告知可以在surface上進行繪制操作 48 mCamera.startPreview(); 49 }catch(Exception e){ 50 Log.e(TAG, "Start preview failed", e); 51 mCamera.release(); 52 mCamera=null; 53 } 54 } 55 });
