When is it necessary, or better to use a SurfaceView instead of a View?
Views are all drawn on the same GUI thread which is also used for all user interaction.
So if you need to update GUI rapidly or if the rendering takes too much time and affects user experience then use SurfaceView.
A few things I've noted:
SurfaceViews contain a nice rendering mechanism that allows threads to update the surface's content without using a handler (good for animation).
Surfaceviews cannot be transparent, they can only appear behind other elements in the view hierarchy.
I've found that they are much faster for animation than rendering onto a View.
For more information (and a great usage example) refer to the LunarLander project in the SDK
's examples section.
updated 05/09/2014
OK. We have official document now. It talked all I have mentioned, in a better way.
Read more detailed here.
Yes, the main difference is surfaceView can be updated on the background thread. However, there are more you might care.
surfaceView has dedicate surface buffer while all the view shares one surface buffer that is allocated by ViewRoot. In another word, surfaceView cost more resources.
surfaceView cannot be hardware accelerated (as of JB4.2) while 95% operations on normal View are HW accelerated using openGL ES.
More work should be done to create your customized surfaceView. You need to listener to the surfaceCreated/Destroy Event, create an render thread, more importantly, synchronized the render thread and main thread. However, to customize the View, all you need to do is override onDraw method.
The timing to update is different. Normal view update mechanism is constraint or controlled by the framework:You call view.invalidate in the UI thread or view.postInvalid in other thread to indicate to the framework that the view should be updated. However, the view won't be updated immediately but wait until next VSYNC event arrived. The easy approach to understand VSYNC is to consider it is as a timer that fire up every 16ms for a 60fps screen. In Android, all the normal view update (and display actually but I won't talk it today), is synchronized with VSYNC to achieve better smoothness. Now,back to the surfaceView, you can render it anytime as you wish. However, I can hardly tell if it is an advantage, since the display is also synchronized with VSYNC, as stated previously.
The main difference is that SurfaceView can be drawn on by background theads but Views can't.
SurfaceViews use more resources though so you don't want to use them unless you have to.
A SurfaceView is a custom view in Android that can be used to drawn inside it.
The main difference between a View and a SurfaceView is that a View is drawn in the
UI Thread, which is used for all the user interaction.
If you want to update the UI rapidly enough and render a good amount of information in
it, a SurfaceView is a better choice.
But there are a few technical insides to the SurfaceView:
1. They are not hardware accelerated.
2. Normal views are rendered when you call the methods invalidate or postInvalidate(), but this does not mean the view will be
immediately updated (A VSYNC will be sent, and the OS decides when
it gets updated. The SurfaceView can be immediately updated.
3. A SurfaceView has an allocated surface buffer, so it is more costly
One of the main differences between surfaceview and view is that to refresh the screen for a normal view we have to call invalidate method from the same thread where the view is defined. But even if we call invalidate, the refreshing does not happen immediately. It occurs only after the next arrival of the VSYNC signal. VSYNC signal is a kernel generated signal which happens every 16.6 ms or this is also known as 60 frame per second. So if we want more control over the refreshing of the screen (for example for very fast moving animation), we should not use normal view class.
On the other hand in case of surfaceview, we can refresh the screen as fast as we want and we can do it from a background thread. So refreshing of the surfaceview really does not depend upon VSYNC, and this is very useful if we want to do high speed animation. I have few training videos and example application which explain all these things nicely. Please have a look at the following training videos.
https://youtu.be/kRqsoApOr9U
https://youtu.be/Ji84HJ85FIQ
https://youtu.be/U8igPoyrUf8
Why use SurfaceView and not the classic View class...
One main reason is that SurfaceView can rapidly render the screen.
In simple words a SV is more capable of managing the timing and render animations.
To have a better understanding what is a SurfaceView we must compare it with the View class.
What is the difference... check this simple explanation in the video
https://m.youtube.com/watch?feature=youtu.be&v=eltlqsHSG30
Well with the View we have one major problem....the timing of rendering animations.
Normally the onDraw() is called from the Android run-time system.
So, when Android run-time system calls onDraw() then the application cant control
the timing of display, and this is important for animation. We have a gap of timing
between the application (our game) and the Android run-time system.
The SV it can call the onDraw() by a dedicated Thread.
Thus: the application controls the timing. So we can display the next bitmap image of the animation.
Related
Is there a good way to draw standard Android View objects on top of a GLSurfaceView and synchronize the movement between the two layers?
My layout looks like
<FrameLayout>
<RelativeLayout>
<MyCustomGLSurfaceView>
</FrameLayout>
The MyCustomGLSurfaceView implements a camera and this camera is moved when the user touches the screen appropriately.
At the end of the onDrawFrame() callback in the renderer I invoke a callback to tell the RelativeLayout that the camera has moved and that it should update the location of any subviews as necessary.
To try and synchronize the two layers I am doing the following:
Set renderMode = RENDERMODE_WHEN_DIRTY within MyCustomGLSurfaceView
Having MyCustomGLSurfaceView implement Choreographer.FrameCallback and in the doFrame(frameTimeNanos: Long) method calling requestRender()
onDrawFrame invokes a callback to indicate the camera has moved and the RelativeLayout updates the position of it’s subviews as necessary.
Delaying the position of the camera 1 frame within the MyCustomGLSurfaceView since it appears that the Android View objects aren't updated on the screen until the following frame whereas the MyCustomGLSurfaceView was updated immediately.
The theory is that by listening for Choreographer callbacks, the rendering of the MyCustomGLSurfaceView is happening at the same time as when the application is re-drawing the standard UI elements.
This seems to work reasonably well but there are noticeable stutters within the Android View object layer. Also positioning the elements in the Android View layer has some odd behaviour when doing it via setting margins (views get destroyed when they're off screen and don't always reappear and sometimes stop being updated at all). I have tried positioning them using translationX / translationY but then the synchronization between the two layers isn't as good.
Is there a good approach for achieving this synchronization?
I have thought that it might be better to use a TextureView as opposed to a GLSurfaceView since the TextureView is composited into the view hierarchy rather than being a separate surface, so I thought maybe synchronization will fall out naturally from that.
The Situation
I started developing for Android, and found that Android's way of handling layouts, animations etc. is not adequate for smooth touch feedback and real-time animations, especially before Android 4.0. So instead, I decided to use the game app approach: use a SurfaceView and define my own drawing code.
The Problem
After a few tests, I discovered that this method required too much CPU for a non-game app, which I believe is due to redrawing static elements 60 times per second.
The First Solution & Flaws
To solve this issue, I modified my code so that the app would redraw the screen (call postInvalidate) only if there were any changes to what should be drawn. This solution solved part of the issue, but the app still had to redraw static elements even if a small button moved a single pixel.
The Question: Possible Better Solution?
For a better solution, I considered how Android dealt with the problem; it had separate View's for every screen element. So I though, maybe I could have one SurfaceView for large, static, content elements and another for small, moving UI elements and achieve a similar effect. My question is, would this actually improve performance the way I described it above?
Thanks.
If you're using postInvalidate(), you should be using a custom View, not a SurfaceView. The whole point of using a SurfaceView is to have a separate layer that is independent of the View UI. If you're overriding onDraw(), you're drawing on the View part, not the Surface part, and just wasting the Surface.
All Views occupy a single layer, no matter how many you have. Each SurfaceView has a separate layer, so having a lot of them will become problematic. In practice you can have no more than three, because of Z-ordering limitations. (See the "multi-surface test" activity in Grafika for an example of three partially transparent SurfaceViews blended with the View UI.)
If you can't render fast enough to maintain 60 fps, you need to consider changing the way you render. Custom Views and OpenGL ES take advantage of hardware acceleration. Canvas rendering onto a SurfaceView Surface does not. On the plus side, you can down-size a SurfaceView's Surface and let the hardware scale it back up; this lets you limit the number of pixels you have to draw each frame, regardless of the display's resolution. (Blog, demo.) If you have a lot of static elements, the best approach may be to render to an off-screen Bitmap, and then just blit the Bitmap every frame.
One approach that will be very fast is to render all of the static elements onto the View part of the SurfaceView, taking care to keep the background transparent, and then render the animated parts on the Surface with GLES. You could use a second SurfaceView, but that adds an additional composition layer, which will degrade system performance if you exceed the number of overlay planes supported by the hardware.
For a deeper understanding of the way Android graphics work, take a look at the graphics architecture doc.
The question is when should i use postInvalidateOnAnimation() over postInvalidate()?
Doc says about postInvalidateOnAnimation(): Cause an invalidate to happen on the next animation time step, typically the next display frame.
But what is next animation time step/next display frame? When will it be called?
I've been puzzling over an animation glitch and stumbled upon this question. Tried to answer below:
What is the next display frame?
This is when all the drawing, layouts and inputs are processed.
The concept of vertical syncing (VSync) is used in the Choreographer class after Android 4.1. This is a signal that is sent traditionally from hardware to say the screen is ready to be redrawn. (It's originates in Cathode Ray Tubes) This is typically around 60Hz on monitors.
The Choreographer is the 'UI threads' message handling loop. On every VSync, the UI messages are processed. These messages will handle inputs and redraw the display. (The Choreographer will also do other things such as skipping frames if the UI is running too slow - this is a common message on the debug console!)
This message loop handling constitutes a frame. When will it be called - every 1/60th of a second on a 60Hz frame rate.
This video
from Google I/O 2012 describes this vsync and the choreographer in more detail.
What is the difference between postInvalidateOnAnimation() over postInvalidate()?
When smooth animations are required use postInvalidateOnAnimation, when redraw is required use postInvalidate().
Reasoning:
This was quite hard to answer, both of these methods are for threads communicating with the UI Thread. So I dug into the Choreographer code
and found this in doFrame()
doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);
doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
postInvalidateOnAnimation will put a callback into the animation callbacks and postInvalidate will will put into the traversal callbacks.
The key difference for me is that the animation callbacks are called before the traversal callbacks (layouts, draws).
This means that animation call backs will be called at almost exactly 60fps (processed first) whereas the traversal callbacks may have some small jitter as the layouts and view drawing is done (less than 1/60 second jitter but probably still noticeable)
Take a look at this class: http://developer.android.com/reference/android/view/Choreographer.html
Short desc from the docs:
Coordinates the timing of animations, input and drawing.
The choreographer receives timing pulses (such as vertical synchronization) from the display subsystem then schedules work to occur as part of rendering the next display frame.
Applications typically interact with the choreographer indirectly using higher level abstractions in the animation framework or the view hierarchy. Here are some examples of things you can do using the higher-level APIs.
i make an app which would fire different small animation, such a falling rotating star or a like a text floating from bottom to top, animated with canvas on a surfaceview
they are all constant once fired,
so i planned 2 ways for that, 1 is a big thread which
handles them all animations, updates each after each other animation 1 after 1
or having for each kind of animation such as a falling star, have it's own thread set up, and at each given point the main activity could have a command go on one of the threads, creating him, and starting, and than forgetting about him, letting him run in the background and at the end of the animation that thread will end it self.
so i don't have to worry about storing each fired threads and such, cause i don't know how many could start at a given time.
so will it be more memory efficient to fire random small short threads or have 1 big thread to handle it all? will it work more smoothly and better?
the animations are simply for visual enchantment and does nothing else, neither does it interact with other animations it simply starts, loops, ends.
i hope u understood :\
You probably want a SurfaceView with one thread handling all of your drawing. Having one thread per animation seems overly-complicated. You can certainly have one method per animation type, e.g. renderStars(), renderText(), etc. that are called whenever your one animation thread renders.
Recommended reading:
The SurfaceView documentation
The Canvas and Drawables API Guide - I've linked to the "On a SurfaceView" section, but you should probably read most of the document.
The Lunar Lander sample app - The online code is currently 404-ing after Google recently revamped their developer site, but this link shows you where to find the code in the SDK manager.
During animation you will have to update your UI on UI Thread you cannot use a different thread for running animations. However, for intensive animation you must use a Gaming Engine or write your own Game Thread, that will first update data of objects as per animation formulas and afterwards draw them on UI thread.
I have multiple animations on a single activity and each animation is its own surface view and thread. Some of these images are animated around a fixed image, it seems that in the thread of the surface draw function it keeps calling the onDraw() function for as long as the thread is running, this repaints the static image as well as the animation....making it very slow. Is there a way i can get it to only refresh or repaint the animated object?
Yes, but you want to use static types and do not instantiate them, this speeds up things a little. And also I don't think you should have those threads on the separate images... You should render a complete screen on a separate thread. This is mobile developmnet, they have hardware limitations, kepp that in mind! =]