The relationship between Surface, SurfaceView, Surfaceholder and Surfaceholder.callback

Please include the URL for reprinting:http://blog.csdn.net/pathuang68/article/details/7351317

1. Surface< /p>

Surface means “surface”. In the SDK documentation, the description of Surface is as follows: “Handle onto a raw buffer that is being managed by the screen compositor”, translated into Chinese is “the native buffer managed by the screen compositor” Handle of the device”, this sentence includes the following two meanings:

1. Through Surface (because Surface is a handle), you can get the native buffer Device and its contents. Just like in C language, you can get the content of a file through a file handle;

2. Rawbuffer ) Is used to save the pixel data of the current window.

Extension, you can think of Surface in Android as a place for drawing graphics or images. According to the general knowledge of Java, we know that drawing is usually done on a Canvas object. From this, we can infer that a Surface object should contain a Canvas object. In fact, this is true, and this can be easily run through debug. The way of the program is proved (Hold the cursor on the object variable surface, a dialog box will pop up, in which the content of the red box, there is a CompatileCanvas member variable in the surface surface) Of course, looking at the source code can also prove this:< /span>


Therefore, on the basis of the two meanings mentioned above, you can add one more:

3. There is a Canvas member in Surface, which is specially used for drawing pictures.

Therefore, the Canvas member in Surface is a place for programmers to draw pictures, just like a blackboard; the native buffer It is used to save data; Surface itself is similar to a handle, you can get the Canvas, native buffer and other aspects of the contents of this handle.

Second, SurfaceView

< span style="font-size:11px">SurfaceView, as the name suggests, is the View of Surface. You can see part or all of the contents of Surface through SurfaceView. Here is a picture Describe the relationship between Surface and SurfaceView vividly:


In other words, Surface can only display its contents through SurfaceView. In this sense, the exact meaning of View in SurfaceView should be the meaning of viewport, which is “viewport”. Friends who have done database design know that a data table has 20 fields, but we often only use one of them. 5 fields, then you can use the SQL statement CREATEVIEW to create a view that only contains the contents of those 5 fields on the basis of the original data table.

On the other hand, SurfaceView is a subclass of View in Android. In fact, all classes used for interface display in Android are subclasses of View, including those invisible and various Layouts.

So, the View in SurfaceView has two meanings:

1. The meaning of viewport

2. SurfaceView is a derived class of View

In Android, Surface is derived from Object and implements the Parcelable interface . Seeing Parcelable makes people naturally think of data containers. SurfaceView is used to display the data in Surface. At this level, Surface is the place to manage data, and SurfaceView is the place to display data.

3. SurfaceHolder

< span style="font-size:11px">SurfaceHolder is an interface that acts like a listener on Surface. Provides access and control of the Surface-related methods behind the SurfaceView (providing access and control over this SurfaceView’s underlying surface). It uses three callback methods to allow us to perceive the creation, destruction or change of the Surface. There is a method getHolder in SurfaceView, which can easily get the SurfaceHolder corresponding to the Surface corresponding to the SurfaceView (a bit awkward).

Except for the SurfaceHolder mentioned below. In addition to Callback, SurfaceHolder also provides many important methods, the most important of which is:

1. abstract voidaddCallback(SurfaceHolder.Callback callback)

adds a SurfaceHolder.Callback callback interface for SurfaceHolder.

2. abstractCanvaslockCanvas()

Get a Canvas Object and lock it. The Canvas object obtained is actually a member of Surface.

3. abstractCanvaslockCanvas(Rectdirty)

Same as above. But only the rectangular area specified by dirty is locked, so the efficiency is higher.

4. abstract voidunlockCanvasAndPost(Canvascanvas) span>

After modifying the data in the Surface, release the sync lock, submit the changes, and then display the new data, and the relevant data in the Surface will be lost.

5. public abstract void setType (int type)

Set the type of Surface and receive the following parameters:

SURFACE_TYPE_NORMAL: Normal Surface that uses RAM to cache native data

SURFACE_TYPE_HARDWARE: Suitable for DMA (Direct memory access) engine and hardware accelerated Surface

SURFACE _TYPE_GPU: Surface suitable for GPU acceleration

SURFACE_TYPE_PUSH_BUFFERS: indicates that the Surface does not contain native data. The data used by the Surface is provided by other objects. This type of Surface is used in the camera image preview, and the Camera is responsible for providing the preview Surface data, so that the image preview will be smoother. If you set this type, you cannot call lockCanvas to get the Canvas object. It should be noted that in the higher version of the Android SDK, the setType method has been depreciated.

The purpose of the synchronization lock mechanism in 2, 3, 4 is to keep the data in the Surface unchanged during the drawing process .


From the height of the design pattern From a point of view, Surface, SurfaceView and SurfaceHolder are essentially the well-known MVC, namely Model-View-Controller. Model is the meaning of model, or data model, or more simply data, which is the Surface here; View is the view, which represents the user interaction interface, which is the SurfaceView here; SurfaceHolder can obviously be understood as the MVC Controller. It seems that the relationship between the three is much clearer.

Four. SurfaceHolder.Callback

As mentioned earlier, SurfaceHolder is an interface, which allows us to perceive the creation of Surface by returning to the method , Destroyed or changed. In fact, this is achieved through its internal static sub-interface SurfaceHolder.Callback. Three interface methods are defined in SurfaceHolder.Callback:

1. abstract voidsurfaceChanged(SurfaceHolderholder, int format, int width, int height)

When any structure occurs on the surface When the sex changes (format or size), this method will be called immediately.

2. abstract voidsurfaceCreated(SurfaceHolderholder)< /span>

When the surface object is created, this method will be called immediately.

3. abstract voidsurfaceDestroyed(SurfaceHolderholder)< /span>

When the surface object is about to be destroyed, this method will be called immediately.

In the Android SDK documentation, about SurfaceView In the description, there is a paragraph like this:

One ​​of the purposes of this class is to provide a surface in which a secondarythread can render into the screen. If you are going to use it this way, you need to be aware of some threading semantics:

– All SurfaceView and SurfaceHolder.Callbackmethods will be called from the thread running the SurfaceView’s window(typically the main thread of the application). They thus need to correctly synchronize with any state that is also touched by the drawing thread.

– You must ensure that the drawingthread only touches the underlying Surface while it is valid – betweenSurfaceHolder.Callback.surfaceCreated() andSurfaceHolder.Callback.surfaceDestroyed().

This passage is very important, and the general meaning is as follows :

One ​​of the purposes of this class is to provide a surface that can be rendered on the screen by another thread (the second thread). If you plan to use this way, you should pay attention to some thread semantics:

– All methods declared in SurfaceView and SurfaceHolder.Callback must be Called from the thread running the SurfaceView window (typically, the main thread of the application. Annotation: UI thread), because they need to correctly synchronize the various states accessed by the drawing thread at the same time.

– It must be ensured that only when the Surface behind it is valid-in SurfaceHolder.Callback.surfaceCreated() and SurfaceHolder.Callback.surfaceDestroyed() Between these two method calls, access it.

Below, we pass a very simple example Let’s get a feel for it (the code is taken fromhttp://www.cnblogs.com/xuling/archive/2011/06/06/android.html and made some structural changes), please pay attention to the comments in the code:

1. Create an Android Project project TestSurfaceView in Eclipse, and choose to generate the default Activity TestSurfaceViewActivity

2. Create a drawing thread as follows:

[java] view plain copy

  1. < span style=“font-size:11px;”>
  2. packagecom.pat.testsurfaceview;
  3. importandroid.graphics.Canvas;< /span>
  4. importandroid.graphics.Color;
  5. import android.graphics.Paint;
  6. importandroid.graphics.Rect;
  7. importandroid.view.SurfaceHolder ;
  8.    
  9. // 绘制线程  
  10. public class MyThread extendsThread  
  11. {  
  12.          private SurfaceHolder holder;  
  13.          private boolean run;  
  14.           
  15.          public MyThread(SurfaceHolder holder)  
  16.          {  
  17.                    this.holder = holder;  
  18.                    run = true;  
  19.          }  
  20.    
  21.          @Override  
  22.          public void run()  
  23.          {  
  24.                    int counter = 0;  
  25.                    Canvas canvas = null;  
  26.                    while(run)  
  27.                    {  
  28.                             // 具体绘制工作  
  29.                             try  
  30.                             {  
  31.                                      // 获取Canvas对象,并锁定之  
  32.                                      canvas= holder.lockCanvas();  
  33.                                       
  34.                                      // 设定Canvas对象的背景颜色  
  35.                                      canvas.drawColor(Color.WHITE);  
  36.                                       
  37.                                      // 创建画笔  
  38.                                      Paintp = new Paint();  
  39.                                      // 设置画笔颜色  
  40.                                      p.setColor(Color.BLACK);  
  41.                                      // 设置文字大小  
  42. < span style="color:black; border-bottom:medium none; border-left:medium none; padding-bottom:0px; margin:0px; padding-left:0px; padding-right:0px; border-top:medium none; border-right:medium none; padding-top:0px">                                     p.setTextSize(30);  
  43.                                       
  44.                                      // 创建一个Rect对象rect  
  45.                                      Rect rect = new Rect(10050380330);  
  46.                                      // 在canvas上绘制rect  
  47. < span style="font-size:14px; color:black; border-bottom:medium none; border-left:medium none; padding-bottom:0px; margin:0px; padding-left:0px; padding-right:0px; border-top:medium none; border-right:medium none; padding-top:0px">                                     canvas.drawRect(rect,p);  
  48.                                      // 在canvas上显示时间  
  49.                                      canvas.drawText(“Interval = “ + (counter++) + ” seconds.”100410, p);  
  50.                                      Thread.sleep(1000);  
  51.                             }  
  52.                             catch(Exception e)  
  53.                             {  
  54.                                      e.printStackTrace();  
  55.                             }  
  56.                             finally  
  57.                             {  
  58.                                      if(canvas != null)  
  59.                                      {  
  60.                                                // 解除锁定,并提交修改内容  
  61.                                                holder.unlockCanvasAndPost(canvas);  
  62.                                      }  
  63.                             }  
  64.                    }  
  65.          }  
  66.    
  67.          public boolean isRun()  
  68.          {  
  69.                    return run;  
  70.          }  
  71.           
  72.          public void setRun(boolean run)  
  73.          {  
  74.                    this.run = run;  
  75.          }  
  76. }  


3.      自定义一个SurfaceView类如下:

[java]  view plain copy

  1. “font-size:11px;”>  
  2. package com.pat.testsurfaceview;  
  3.    
  4. import android.content.Context;  
  5. import android.view.SurfaceHolder;  
  6. import android.view.SurfaceView;  
  7.    
  8. public class MySurfaceView extends SurfaceView  
  9. implements  
  10. SurfaceHolder.Callback  
  11. {  
  12.          private SurfaceHolder holder;  
  13.          private MyThread myThread;  
  14.           
  15.          publicMySurfaceView(Context context)  
  16.          {  
  17.                    super(context);  
  18.                     
  19.                    // 通过SurfaceView获得SurfaceHolder对象  
  20.                    holder = getHolder();  
  21.                     
  22.                    // 为holder添加回调结构SurfaceHolder.Callback  
  23.                    holder.addCallback(this);  
  24.                     
  25.                    // 创建一个绘制线程,将holder对象作为参数传入,这样在绘制线程中就可以获得holder  
  26.                    // 对象,进而在绘制线程中可以通过holder对象获得Canvas对象,并在Canvas上进行绘制  
  27.                    myThread = new MyThread(holder);  
  28.          }  
  29.    
  30.          // 实现SurfaceHolder.Callback接口中的三个方法,都是在主线程中调用,而不是在绘制线程中调用的  
  31.          @Override  
  32.          public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)  
  33.          {  
  34.          }  
  35.    
  36.          @Override  
  37.          public void surfaceCreated(SurfaceHolder holder)  
  38.          {  
  39.                    // 启动线程。当这个方法调用时,说明Surface已经有效了  
  40.                    myThread.setRun(true);  
  41.                    myThread.start();  
  42.          }  
  43.    
  44.          @Override  
  45.          public void surfaceDestroyed(SurfaceHolderholder)  
  46.          {  
  47.                    // 结束线程。当这个方法调用时,说明Surface即将要被销毁了  
  48.                    myThread.setRun(false);  
  49.          }  
  50. }  

 

4.    修改TestSurfaceViewActivity.java代码,使之如下:

[java]  view plain copy

  1. “font-size:11px;”>  
  2. package com.pat.testsurfaceview;  
  3.    
  4. import android.app.Activity;  
  5. import android.os.Bundle;  
  6.    
  7. public class TestSurfaceViewActivity extends Activity  
  8. {  
  9.     @Override  
  10.     public void onCreate(Bundle savedInstanceState)  
  11.     {  
  12.         super.onCreate(savedInstanceState);  
  13.         //setContentView(R.layout.main);  
  14.         setContentView(new MySurfaceView(this) );  
  15.     }  
  16. }  

 

运行结果:

 

很显然,我们可以在MyThread的run方法中,做很多更有意思的事情。弄清楚了Surface、SurfaceView、SurfaceHolder和SurfaceHolder.Callback这些概念,以及它们之间的关系,对我们更好地使用它们应该会有相当大的帮助。

[java]  view plain copy

  1. “f ont-size:11px;”>  
  2. package com.pat.testsurfaceview;  
  3.    
  4. import android.graphics.Canvas;  
  5. import android.graphics.Color;  
  6. import android.graphics.Paint;  
  7. import android.graphics.Rect;  
  8. importandroid.view.SurfaceHolder;  
  9.    
  10. // 绘制线程  
  11. public class MyThread extendsThread  
  12. {  
  13.          private SurfaceHolder holder;  
  14.          private boolean run;  
  15.           
  16.          public MyThread(SurfaceHolder holder)  
  17.          {  
  18.                    this.holder = holder;  
  19.                    run = true;  
  20.          }  
  21.    
  22.          @Override  
  23.          public void run()  
  24.          {  
  25.                    int counter = 0;  
  26.                    Canvas canvas = null;  
  27.                    while(run)  
  28.                    {  
  29.                             // 具体绘制工作  
  30.                             try  
  31.                             {  
  32.                                      // 获取Canvas对象,并锁定之  
  33.                                      canvas= holder.lockCanvas();  
  34.                                       
  35.                                      // 设定Canvas对象的背景颜色  
  36.                                      canvas.drawColor(Color.WHITE);  
  37.                                       
  38.                                      // 创建画笔  
  39.                                      Paintp = new Paint();  
  40.                                      // 设置画笔颜色  
  41.                                      p.setColor(Color.BLACK);  
  42.                                      // 设置文字大小  
  43.                                      p.setTextSize(30);  
  44.                                       
  45.                                      // 创建一个Rect对象rect  
  46.                                      Rect rect = new Rect(10050380330);  
  47.                                      // 在canvas上绘制rect  
  48.                                      canvas.drawRect(rect,p);  
  49.                                      // 在canvas上显示时间  
  50.                                      canvas.drawText(“Interval = “ + (counter++) + ” seconds.”100410, p);  
  51.                                      Thread.sleep(1000);  
  52.                             }  
  53.                             catch(Exception e)  
  54.                             {  
  55.                                      e.printStackTrace();  
  56.                             }  
  57.                             finally  
  58.                             {  
  59.                                      if(canvas != null)  
  60.                                      {  
  61.                                                // 解除锁定,并提交修改内容  
  62.                                                holder.unlockCanvasAndPost(canvas);  
  63.                                      }  
  64.                             }  
  65.                    }  
  66.          }  
  67.    
  68.          public boolean isRun()  
  69.          {  
  70.                    return run;  
  71.          }  
  72.           
  73.          public void setRun(boolean run)  
  74.          {  
  75.                    this.run = run;  
  76.          }  
  77. }  

[java]  view plain copy

[java]  view plain copy

[java]  view plain copy

  1. “font-size:11px;”>  
  2. package com.pat.testsurfaceview;  
  3.    
  4. import android.content.Context;  
  5. import android.view.SurfaceHolder;  
  6. < span class="keyword" style="color:#06699; border-bottom:medium none; border-left:medium none; padding-bottom:0px; margin:0px; padding-left:0px; padding-right:0px; border-top:medium none; font-weight:bold; border-right:medium none; padding-top:0px">import android.view.SurfaceView;  
  7.    
  8. public class MySurfaceView extends SurfaceView  
  9. implements  
  10. SurfaceHolder.Callback  
  11. {  
  12.          private SurfaceHolder holder;  
  13.          private MyThread myThread;  
  14.           
  15.          publicMySurfaceView(Context context)  
  16.          {  
  17.                    super(context);  
  18.                     
  19.                    // 通过SurfaceView获得SurfaceHolder对象  
  20.                    holder = getHolder();  
  21.                     
  22.                    // 为holder添加回调结构SurfaceHolder.Callback  
  23.                    holder.addCallback(this);  
  24.                     
  25.                    // 创建一个绘制线程,将holder对象作为参数传入,这样在绘制线程中就可以获得holder  
  26.                    // 对象,进而在绘制线程中可以通过holder对象获得Canvas对象,并在Canvas上进行绘制  
  27.                    myThread = new MyThread(holder);  
  28.          }  
  29.    
  30.          // 实现SurfaceHolder.Callback接口中的三个方法,都是在主线程中调用,而不是在绘制线程中调用的  
  31.          @Override  
  32.          public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)  
  33.          {  
  34.          }  
  35.    
  36.          @Override  
  37.          public void surfaceCreated(SurfaceHolder holder)  
  38.          {  
  39.                    // 启动线程。当这个方法调用时,说明Surface已经有效了  
  40.                    myThread.setRun(true);  
  41.                    myThread.start();  
  42.          }  
  43.    
  44.          @Override  
  45.          public void surfaceDestroyed(SurfaceHolderholder)  
  46.          {  
  47.                    // 结束线程。当这个方法调用时,说明Surface即将要被销毁了  
  48.                    myThread.setRun(false);  
  49.          }  
  50. }  

[java]  view plain copy

[java]  view plain copy

[java]  view plain copy

  1. “font-size:11px;”>  
  2. package com.pat.testsurfaceview;  
  3.    
  4. import android.app.Activity;  
  5. import android.os.Bundle;  
  6.    
  7. public class TestSurfaceViewActivity extends Activity  
  8. {  
  9.     @Override  
  10.     public void onCreate(Bundle savedInstanceState)  
  11.     {  
  12.         super.onCreate(savedInstanceState);  
  13.         //setContentView(R.layout.main);  
  14.         setContentView(new MySurfaceView(this));  
  15.     }  
  16. }  

[java]  view plain copy

[java]  view plain copy

Leave a Comment

Your email address will not be published.