SurfaceView

What is SurfaceView?

Why What about SurfaceView? Surface means surface, surface means, then SurfaceView refers to a View object on the surface. Why is it on the surface? This is because it is a bit special and different from other Views. Other Views are drawn outside the surface, and they act as surface objects. Suppose you want to draw on a ball, then the surface of the ball is used as your canvas object. What you draw will block its surface. We do not use SurfaceView by default, so the surface of the ball is blank. If we use SurfaceView , We can understand that the surface of the ball itself has textures, you paint on top of the textures, if your painting is translucent, then you will be able to see the textures of the sphere itself through the things you draw . The SDK documentation says: SurfaceView is to dig a hole in the Window, it is displayed in this hole, and other Views are displayed on the Window, so the View can be displayed on the SurfaceView, or you can add some layers on the SurfaceView. Above.

SurfaceView also There are other features. We mentioned above that it can control the number of frames. What is it to control? This requires understanding its use mechanism. Generally in many game designs, we open up a background thread to calculate game-related data, and then refresh the view object based on the new calculated data. Since drawing operations on the View can only be performed on the UI thread, when you are in After another thread calculates the data, you need to call the View.invalidate method to notify the system to refresh the View object, so the game-related data also needs to be accessible to the UI thread. This design architecture is more complicated. If the background computing thread can How good would it be to directly access the data and then update the View object. We know that the View update can only be done in the UI thread, so there is no way to use a custom View to do so, but SurfaceView will do. One of its good uses is to allow other threads (not UI threads) to draw graphics (using Canvas). According to this feature, you can control the number of frames. If you let this thread 1 Draw 50 times per second, then the last displayed is 50 frames.

How to use SurfaceView?

First SurfaceView It is also a View, and it also has its own life cycle. Because it needs another thread to perform drawing operations, we can create a new thread during the initialization phase of its life cycle, and then start to perform drawing. At the end of the life cycle, we insert the operation to end the drawing thread. These are completed by a SurfaceHolder object inside. SurfaceHolder, as the name implies, it saves a reference to a team of Surface objects, and our drawing method is to operate this Surface. SurfaceHolder saves a reference to Surface, so it uses it to handle the life cycle of Surface. In the final analysis, the life cycle of SurfaceView In fact, it is the life cycle of the Surface. Because the SurfaceHolder saves the reference to the Surface, the SurfaceHolder is used to handle the initialization of the life cycle. First, let’s take a look at the general steps to create a SurfaceView, first take a look at the code:

 import android.app.Activity; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.os.Bundle; import android.view.View; public class AnimateViewActivity extends Activity {@Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState); setContentView(new AnimateView(this));} class AnimateView extends View{ float radius = 10; Paint paint; public AnimateView(Context context) {super(context); paint = new Paint(); paint.setColor(Color.YELLOW); paint.setStyle(Paint.Style.STROKE);} @Override protected void onDraw(Canvas canvas) {canvas.translate(200, 200); canvas.drawCircle(0, 0, radius++, paint); if(radius> 100) {radius = 10;} invalidate();//Call this method to let the system automatically refresh the view}} }

In the above code, we executed the init initialization method in the SurfaceView construction method. In this method, we first obtain the SurfaceHolder object in the SurfaceView, and then pass it Set the life cycle callback method of Surface, and use the DemoSurfaceView class itself as the callback method proxy class. The surfaceCreated method is the method that will be called when the SurfaceView is displayed, so you need to open the drawing thread here. The surfaceDestroyed method is the method called when the SurfaceView is hidden and will be destroyed. Here you can close the drawing thread. After the above example runs, nothing is displayed, because there is no thread defined to execute drawing. Let’s modify the code and use a thread to draw a gradually larger circle:

 import android .content.Context; import android.view.SurfaceHolder; import android.view.SurfaceHolder.Callback; import android.view.SurfaceView; public class DemoSurfaceView extends SurfaceView implements Callback{ public DemoSurfaceView(Context context) {super(context); init( ); //Initialize, set life cycle callback method} private void init(){ SurfaceHolder holder = getHolder(); holder.addCallback(this); //Set Surface life cycle callback} @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {} @Override public void surfaceCreated(SurfaceHolder holder) {} @Override public void surfaceDestroyed(SurfaceHolder holder) {} }

The above code writes an animation effect made with SurfaceView. Its effect is the same as the custom View above, but the SurfaceView here can control the animation The number of frames. A LoopThread thread is built in SurfaceView. The function of this thread is to draw graphics. A LoopThread instance is instantiated in SurfaceView. Generally, this operation will be placed in the SurfaceView’s construction method. Then by inserting some operations in the life cycle callback method of SurfaceHolder in SurfaceView, when Surface is created (when SurfaceView is displayed on the screen), open LoopThread to perform drawing, LoopThread will always refresh the SurfaceView object, and stop when SurfaceView is hidden Change the thread to release resources. Here are a few things to pay attention to:

1. Because SurfaceView allows custom threads to operate Surface objects to perform drawing methods, and you may define multiple threads to perform drawing at the same time, so remember to add synchronization operations when you get the Canvas object in SurfaceHolder, To avoid two different threads operating the same Canvas object at the same time, remember to call the SurfaceHolder.unlockCanvasAndPost method to release the Canvas lock when the operation is completed.

2. When calling doDraw to perform drawing, because of the characteristics of SurfaceView, it will retain the previously drawn graphics, so you need to clear the graphics left during the last drawing. (View does not, it defaults to automatically clear the contents of the view when calling the View.onDraw method).

3. Remember to close the LoopThread that performs drawing in the background in the callback method: onSurfaceDestroyed method, here is the use of the join method. This involves the issue of how the thread is closed. Most people suggest to use a flag bit: isRunning to determine whether the thread should stop running. If you want to close the thread, just change isRunning to false, and the thread will automatically execute the run method. quit.

Summary:

Through the above analysis, Now everyone should be able to use SurfaceView simply. In general, the differences between SurfaceView and View are:

1. SurfaceView allows other threads to update the view object (execute the drawing method) but View does not allow it. It only allows the UI thread to update the view object.

2. SurfaceView is placed in the other lowest view hierarchy, all other view layers are on top of it, so some layers can be added on top of it, and it cannot be transparent.

3. It performs animation more efficiently than View, and you can control the number of frames.

4. Because its definition and use are more complex than View, and it occupies more resources. Unless it can’t be done with View, use SurfaceView or it’s better to use View. (Snakes, Tetris, Chess, etc. The frame number is relatively low, you can use View to do it)

5. SurfaceView’s digging process

The window type of SurfaceView is generally TYPE_APPLICATION_MEDIA or TYPE_APPLICATION_MEDIA_OVERLAY, that is, its Z-axis position is smaller than the Z position of its host window. In order to ensure that the UI of SurfaceView is visible, SurfaceView needs to dig a hole in the top of its host window. In fact, it sets a transparent area on the drawing surface of its host window so that it can display itself.

From the creation process of SurfaceView’s drawing surface, you can know that SurfaceView When attached to the host window, it will request to set a transparent area on the host window, and whenever its host window refreshes its own UI, it will collect all the transparent areas set by the SurfaceView embedded in it Get up, and then notify the WindowManagerService service to set a total transparent area for it.

From the creation process of SurfaceView’s drawing surface, you can know that SurfaceView When attached to the host window, the member function onAttachedToWindow of the SurfaceView class will be called. The member function onAttachedToWindow of the SurfaceView class will request to set a transparent area on the host window while it is being called.

In conclusion, SurfaceView has the following three characteristics:

A. With independence Drawing surface;

B. You need to dig a hole in the host window to show yourself;

C. Its UI drawing can be performed in a separate thread, so that complex UI drawing can be performed without affecting the main thread of the application in response to user input.

What is double buffering?

drawing directly on the window without a canvas is called unbuffered drawing . A canvas is used, and all the content is drawn on the canvas first, and then the whole is drawn on the window. It should be called single-buffer drawing, and that canvas is a buffer. Two canvases are used, one for temporary drawing and the other for final drawing. This is called double-buffer drawing.

< span style="line-height:30px">surfaceView itself implements double buffering, but View does not. In fact, you can also implement the view yourself, but the implemented structure is not as good as the surfaceView.

< span style="line-height:30px"> SurfaceView locks the canvas through surfaceHolder.lockCanvas to draw the next picture, and then refresh the interface through another thread to draw the picture.

< span style="line-height:30px"> view is to draw pictures directly in ondraw and refresh the interface. In fact, the view can also implement a double buffering mechanism. You can draw the next bitmap in another ondraw method (see: http://www.voidcn.com/article/p-xjhhcael-bmm.html), or you can Another thread is opened to handle operations other than drawing pictures (see: http://topic.csdn.net/u/20110901/23/e283f805-20dc-40c3-8381-403dd1ca69b0.html), and the dual view is realized buffer.

< span style="line-height:30px">Why is dynamic drawing surfaceView better than View?

Because the View is drawn in the UI main thread, the main thread will be blocked when drawing. If the ontouch event is processed more Otherwise, it will cause the interface card. The surfaceView is drawn by a separate thread, coupled with a double buffer mechanism, so it must be efficient. Won’t get stuck. In fact, when the view is generally implemented nowadays, the bitmap is usually generated in the ondraw before drawing. So the role of double buffering is not so obvious.

Leave a Comment

Your email address will not be published.