I'm learning from the Documentation of Suface, Suface Flinger, SurfaceView, SurfaceHolder and Bitmap. I have found following definitions:
Surface
Surface is a collection of pixels. A Surface is an object holding pixels that are being composited to the screen. Every window you see on the screen (a dialog, your full-screen activity, the status bar) has its own surface that it draws in to, and Surface Flinger renders these to the final display in their correct Z-order. A surface typically has more than one buffer (usually two) to do double-buffered rendering: the application can be drawing its next UI state while the surface flinger is compositing the screen using the last buffer, without needing to wait for the application to finish drawing.
SurfaceView
This class is used to present a live camera preview to the user.
A SurfaceView is a special implementation of View that also creates its own dedicated Surface for the application to directly draw into (outside of the normal view hierarchy, which otherwise must share the single Surface for the window)
Bitmap
A Bitmap is a wrapper for collection of pixels,it is simply an array of pixels with some other convenient functions.
Canvas
Canvas is a class that contains all the drawing methods. It is similar to Graphics class in AWT/Swing in Java. It has all the logic on how to draw, a box etc. A Canvas operates on a Bitmap.
But I'm not clear about SurfaceHolder and SurfaceFlinger and according to above definition bitmap is also container of pixel and Surface too.
Can you help to give me clear understanding the definition of all these objects?
A Canvas is a basic context for doing drawing with the graphics API. You can create your own Canvas wrapping a Bitmap for doing off-screen drawing, and of course the UI framework will pass Canvases to widgets for them to draw themselves into. All these widgets are subclasses of View. Or, if they can contain other widgets, then they subclass from ViewGroup (which is a subclass of View).
If you want to do high-frame-rate animations, then you need to subclass from SurfaceView (or its subclass GLSurfaceView, if you want to do on-screen OpenGL-ES rendering). Each SurfaceView has a SurfaceHolder, which has lockCanvas methods that you can call at any time to get a Canvas into which to draw an updated display and post back for the user to see immediately via unlockCanvasAndPost.
For more info, see 2D graphics concepts and Custom widget tips
Related
I have a relativelayout with three full screen child views of the same custom view class. I am wondering whether I should be worried about memory. Judging by this answer:
Understanding Canvas and Surface concepts
All views get passed the same canvas with underlying bitmap to draw on so that the memory is not tripled. Can anyone confirm?
It would make sense, otherwise a full screen textview would be very inefficient.
Bonus: is the purpose of canvas to define a drawable area of a bitmap and translating the view coordinates to bitmap coordinates?
As per the documentation http://developer.android.com/guide/topics/graphics/2d-graphics.html#draw-with-canvas:
When you're writing an application in which you would like to perform specialized drawing and/or control the animation of graphics, you should do so by drawing through a Canvas. A Canvas works for you as a pretense, or interface, to the actual surface upon which your graphics will be drawn — it holds all of your "draw" calls. Via the Canvas, your drawing is actually performed upon an underlying Bitmap, which is placed into the window.
In the onDraw(Canvas canvas), you are given a canvas object. This canvas has an underlying bitmap. All views are not given the same canvas. Canvas is just a layer above the common bitmap (which is pixels on the screen). canvas offers you to manipulate the bitmap as much as you want. So every view has a canvas, but not it's own bitmap.
So no, as far as memory is concerned, three view doesn't mean memory is tripled, because there is just one bitmap. You could however create your own bitmap, if you do so, then you will be jogging up the memory. If you create 3 bitmaps with size of the screen, your memory will be tripled.
I would like to display the score when user click on a button (make +1 fly to top of the screen) and I wonder if it is better to use a surfaceview or view?
See here for more information on the differences between SurfaceView and View.
For your case, View would probably be simpler and appropriate.
If your application does not require a significant amount of processing or frame-rate speed (perhaps for a chess game, a snake game, or another slowly-animated application), then you should consider creating a custom View component and drawing with a Canvas in View.onDraw(). The most convenient aspect of doing so is that the Android framework will provide you with a pre-defined Canvas to which you will place your drawing calls.
A SurfaceView, on the other hand, is not drawn on the main thread and instead takes place on a secondary thread:
The SurfaceView is a special subclass of View that offers a dedicated drawing surface within the View hierarchy. The aim is to offer this drawing surface to an application's secondary thread, so that the application isn't required to wait until the system's View hierarchy is ready to draw. Instead, a secondary thread that has reference to a SurfaceView can draw to its own Canvas at its own pace.
I think view fits this scenario better. You could translate a view to the top of the screen.
So far, I've only used SurfaceView for rendering background graphics. Of course you could do it using SurfaceView, but that would bring more complexity in terms of coding. You need to draw this "+1" and calculate its position from frame to frame.
Using a View, you could just apply an animation, set the duration, and that should do the trick.
Working with a SurfaceView to make a 2d game i do not know who to put a background image in it efficiently.
I want to avoid drawing it each frame because it is an static image, any help?
The SurfaceView's Surface is a single layer. You can specify a dirty rect to reduce your draw area when you lock the Canvas, but you have to draw everything in the rect every frame -- background and all.
You could use a pair of SurfaceViews, one at the default Z-ordering, one at "media" depth. Use SurfaceView.setZOrderMediaOverlay() to do that. The layers will be composited by the system before being rendered.
If you were using OpenGL ES rather than Canvas, it'd generally be more efficient to just redraw the background from a texture each time. (If HWC runs out of overlays, that's essentially what SurfaceFlinger is doing anyway.)
See the "multi-surface test" in Grafika for an example of using multiple overlapping surfaces.
I'm struggling to understand the process of drawing to SurfaceView and therefore the whole Surface/Canvas/Bitmap system, which is used in Android.
I've read all articles and API documentation pages, which I was able to find on android-developers site, a few tutorials of android graphics, LunarLander source code and this question.
Please tell me, which of these statements are true, which are not, and why.
Canvas has its own Bitmap attached to it. Surface has its own Canvas attached to it.
All View's of window share the same Surface and thus share the same Canvas.
SurfaceView is subclass of View, which, unlike other View's subclasses and View itself, has its own Surface to draw in.
There is also one additional question:
Why is there a need for a Surface class, if there is already a Canvas for high-level operations with bitmap. Give an example of a situation where Canvas is non-suitable for doing work which Surface can do.
Here are some definitions:
A Surface is an object holding pixels that are being composited to the screen. Every window you see on the screen (a dialog, your full-screen activity, the status bar) has its own surface that it draws in to, and Surface Flinger renders these to the final display in their correct Z-order. A surface typically has more than one buffer (usually two) to do double-buffered rendering: the application can be drawing its next UI state while the surface flinger is compositing the screen using the last buffer, without needing to wait for the application to finish drawing.
A window is basically like you think of a window on the desktop. It has a single Surface in which the contents of the window is rendered. An application interacts with the Window Manager to create windows; the Window Manager creates a Surface for each window and gives it to the application for drawing. The application can draw whatever it wants in the Surface; to the Window Manager it is just an opaque rectangle.
A View is an interactive UI element inside of a window. A window has a single view hierarchy attached to it, which provides all of the behavior of the window. Whenever the window needs to be redrawn (such as because a view has invalidated itself), this is done into the window's Surface. The Surface is locked, which returns a Canvas that can be used to draw into it. A draw traversal is done down the hierarchy, handing the Canvas down for each view to draw its part of the UI. Once done, the Surface is unlocked and posted so that the just drawn buffer is swapped to the foreground to then be composited to the screen by Surface Flinger.
A SurfaceView is a special implementation of View that also creates its own dedicated Surface for the application to directly draw into (outside of the normal view hierarchy, which otherwise must share the single Surface for the window). The way this works is simpler than you may expect -- all SurfaceView does is ask the window manager to create a new window, telling it to Z-order that window either immediately behind or in front of the SurfaceView's window, and positioning it to match where the SurfaceView appears in the containing window. If the surface is being placed behind the main window (in Z order), SurfaceView also fills its part of the main window with transparency so that the surface can be seen.
A Bitmap is just an interface to some pixel data. The pixels may be allocated by Bitmap itself when you are directly creating one, or it may be pointing to pixels it doesn't own such as what internally happens to hook a Canvas up to a Surface for drawing. (A Bitmap is created and pointed to the current drawing buffer of the Surface.)
Also please keep in mind that, as this implies, a SurfaceView is a pretty heavy-weight object. If you have multiple SurfaceViews in a particular UI, stop and think about whether this is really needed. If you have more than two, you almost certainly have too many.
Here is a very basic and simple conceptual overview of how interaction happens among the Window, Surface, Canvas, and Bitmap.
Sometimes, a visual representation helps a lot in understanding twisted concepts.
I hope this graphic could help someone.
A Bitmap is simply a wrapper for a collection of pixels. Think of it as an array of pixels with some other convenient functions.
The Canvas is simply the class that contains all the drawing methods. It is similar to the Graphics class in AWT/Swing if you are familiar with that. All the logic on how to draw a circle, or a box, etc is contained inside Canvas. A canvas draws on a Bitmap or an open GL container but there is no reason why in the future it could be extended to draw onto other types of rasters.
SurfaceView is a View that contains a Surface. A surface is similar to a bitmap (it has a pixel store). I do not know how it is implemented but I'd imagine it is a some kind of Bitmap wrapper with extra methods for things that are directly related to screen displays (That is the reason for a surface, a Bitmap is too generic). You can get a Canvas from your Surface which is really getting the Canvas associated with the underlying Bitmap.
Your questions.
1.Canvas has its own Bitmap attached to it. Surface has its own Canvas attached to it.
Yes, a canvas operates on a Bitmap (or an open GL panel). Surface gives you a Canvas that is operating on whatever Surface is using for its Bitmap style pixel store.
2.All View's of window share the same Surface and thus share the same Canvas.
No. You could have as many surface views as you want.
3.SurfaceView is subclass of View, which, unlike other View's subclasses and View itself, has its own Surface to draw in.
Yes. Just like ListView is a subclass of View that has its own List data structure. Each subclass of View does something different.
I'm struggling to understand the process of drawing to SurfaceView and therefore the whole Surface/Canvas/Bitmap system, which is used in Android.
I've read all articles and API documentation pages, which I was able to find on android-developers site, a few tutorials of android graphics, LunarLander source code and this question.
Please tell me, which of these statements are true, which are not, and why.
Canvas has its own Bitmap attached to it. Surface has its own Canvas attached to it.
All View's of window share the same Surface and thus share the same Canvas.
SurfaceView is subclass of View, which, unlike other View's subclasses and View itself, has its own Surface to draw in.
There is also one additional question:
Why is there a need for a Surface class, if there is already a Canvas for high-level operations with bitmap. Give an example of a situation where Canvas is non-suitable for doing work which Surface can do.
Here are some definitions:
A Surface is an object holding pixels that are being composited to the screen. Every window you see on the screen (a dialog, your full-screen activity, the status bar) has its own surface that it draws in to, and Surface Flinger renders these to the final display in their correct Z-order. A surface typically has more than one buffer (usually two) to do double-buffered rendering: the application can be drawing its next UI state while the surface flinger is compositing the screen using the last buffer, without needing to wait for the application to finish drawing.
A window is basically like you think of a window on the desktop. It has a single Surface in which the contents of the window is rendered. An application interacts with the Window Manager to create windows; the Window Manager creates a Surface for each window and gives it to the application for drawing. The application can draw whatever it wants in the Surface; to the Window Manager it is just an opaque rectangle.
A View is an interactive UI element inside of a window. A window has a single view hierarchy attached to it, which provides all of the behavior of the window. Whenever the window needs to be redrawn (such as because a view has invalidated itself), this is done into the window's Surface. The Surface is locked, which returns a Canvas that can be used to draw into it. A draw traversal is done down the hierarchy, handing the Canvas down for each view to draw its part of the UI. Once done, the Surface is unlocked and posted so that the just drawn buffer is swapped to the foreground to then be composited to the screen by Surface Flinger.
A SurfaceView is a special implementation of View that also creates its own dedicated Surface for the application to directly draw into (outside of the normal view hierarchy, which otherwise must share the single Surface for the window). The way this works is simpler than you may expect -- all SurfaceView does is ask the window manager to create a new window, telling it to Z-order that window either immediately behind or in front of the SurfaceView's window, and positioning it to match where the SurfaceView appears in the containing window. If the surface is being placed behind the main window (in Z order), SurfaceView also fills its part of the main window with transparency so that the surface can be seen.
A Bitmap is just an interface to some pixel data. The pixels may be allocated by Bitmap itself when you are directly creating one, or it may be pointing to pixels it doesn't own such as what internally happens to hook a Canvas up to a Surface for drawing. (A Bitmap is created and pointed to the current drawing buffer of the Surface.)
Also please keep in mind that, as this implies, a SurfaceView is a pretty heavy-weight object. If you have multiple SurfaceViews in a particular UI, stop and think about whether this is really needed. If you have more than two, you almost certainly have too many.
Here is a very basic and simple conceptual overview of how interaction happens among the Window, Surface, Canvas, and Bitmap.
Sometimes, a visual representation helps a lot in understanding twisted concepts.
I hope this graphic could help someone.
A Bitmap is simply a wrapper for a collection of pixels. Think of it as an array of pixels with some other convenient functions.
The Canvas is simply the class that contains all the drawing methods. It is similar to the Graphics class in AWT/Swing if you are familiar with that. All the logic on how to draw a circle, or a box, etc is contained inside Canvas. A canvas draws on a Bitmap or an open GL container but there is no reason why in the future it could be extended to draw onto other types of rasters.
SurfaceView is a View that contains a Surface. A surface is similar to a bitmap (it has a pixel store). I do not know how it is implemented but I'd imagine it is a some kind of Bitmap wrapper with extra methods for things that are directly related to screen displays (That is the reason for a surface, a Bitmap is too generic). You can get a Canvas from your Surface which is really getting the Canvas associated with the underlying Bitmap.
Your questions.
1.Canvas has its own Bitmap attached to it. Surface has its own Canvas attached to it.
Yes, a canvas operates on a Bitmap (or an open GL panel). Surface gives you a Canvas that is operating on whatever Surface is using for its Bitmap style pixel store.
2.All View's of window share the same Surface and thus share the same Canvas.
No. You could have as many surface views as you want.
3.SurfaceView is subclass of View, which, unlike other View's subclasses and View itself, has its own Surface to draw in.
Yes. Just like ListView is a subclass of View that has its own List data structure. Each subclass of View does something different.