Surfaceview is most suitable for game development in Android. This article will demonstrate the implementation of two commonly used drawing refresh policies in surfaceview.
First, let's take a look at the two clips used in this example:
Bj.jpg is a gradient Chart Used as the background.
Question.png is a translucent image that we want to place and rotate around its center.
The implementation code is as follows:
Package skyd. surfaceviewtest; import android. app. activity; import android. content. context; import android. graphics. bitmap; import android. graphics. bitmapfactory; import android. graphics. canvas; import android. graphics. matrix; import android. graphics. paint; import android. OS. bundle; import android. view. surfaceholder; import android. view. surfaceview; public class main extends activity {@ override public void oncreate (bundle savedinstancestate) {super. oncreate (savedinstancestate); setcontentview (New mysurfaceview (this);} // custom surfaceview subclass class mysurfaceview extends surfaceview implements surfaceholder. callback {// background image private bitmap backgroundimage; // question mark image private bitmap questionimage; surfaceholder holder; Public mysurfaceview (context) {super (context); backgroundimage = bitmapfactory. decoderesource (getresources (), R. drawable. BG); questionimage = bitmapfactory. decoderesource (getresources (), R. drawable. question); holder = This. getholder (); // get Holder. addcallback (this) ;}@ override public void surfacechanged (surfaceholder holder, int format, int width, int height) {// todo auto-generated method stub} @ override public void surfacecreated (surfaceholder holder) {// start the custom thread new thread (New mythread ()). start () ;}@ override public void surfacedestroyed (surfaceholder holder) {// todo auto-generated method stub} // custom Thread class mythread implements runnable {@ override public void run () {canvas = NULL; int rotate = 0; // rotation angle variable while (true) {try {canvas = holder. lockcanvas (); // obtain the canvas paint mpaint = new paint (); // draw the background canvas. drawbitmap (backgroundimage, 0, 0, mpaint); // create a matrix to control image rotation and moving matrix m = new matrix (); // set the Rotation Angle M. postrotate (rotate + = 48) % 360, questionimage. getwidth ()/2, questionimage. getheight ()/2); // set the left margin and top margin M. posttranslate (47, 47); // draw a question mark image canvas. drawbitmap (questionimage, M, mpaint); // sleep to control the maximum frame rate to about 30 frames per second. sleep (33);} catch (exception e) {} finally {holder. unlockcanvasandpost (canvas); // unlock the canvas and submit the painted image }}}}}}
Running Effect in the simulator:
(Note: The question mark graph is continuously rotating)
This looks good, but there is a problem: the maximum frame rate we set in the Code is 30 frames per second, and the frame rate during actual operation can be seen as not more than 30 frames according to the visual test, this is because the program re-draws the entire screen at each frame, and is used for drawing processing for too much time, so it is difficult to reach the maximum frame rate.
Dirty rectangle refresh
Next, we will use the dirty rectangle refresh method to optimize the performance. The so-called dirty rectangle refresh means to refresh the rectangular area where only the changed part is located, and not refresh other useless parts, to reduce resource waste.
When obtaining the canvas, we can assign a parameter to it to declare which part of the canvas we need, so that we can only get control of this part:
This is very simple, but you will find a strange situation if you run it directly after the change:
The question mark pattern may become defective.
Aha, this is exactly the purpose of using a translucent pattern as an example. Through this shadow, we can see that overwrite and refresh is actually to draw each new image to the previous frame, therefore, if the image is translucent, we need to consider the problem caused by repeated overlays, and if the image is completely opaque, there will be no problem.
The background will flash back and forth between the background image and the black background.
This problem is actually caused by surfaceview's dual buffering mechanism. I understand that it will buffer the first two frames of images and deliver them to the next frame for overwrite, in this way, because we only draw the background in the first frame, the second frame is in the non-Background State, and it is maintained through the dual buffer mechanism, the solution is to draw the background in both the first frames:
Now there is no problem (if you change to an opaque image, it will be okay ):
Although it still cannot reach the maximum frame rate, it is not bad. running on a real machine will be faster, close to the maximum frame rate.
Post from: http://www.cnblogs.com/SkyD/archive/2010/11/08/1871423.html