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! =]
Related
I have icons which are represented as View's and all drawing are fully calculating in onDraw method with 'invalidation' on every frame (https://github.com/torryharris/Skycons). I have no ability to get these icons in gif format or other so I need to optimize their drawing because after like 30 second I get 'XXX skiped frame' message in logcat and frozen ui. I know that in OpenGL you could make calculating in background thread and then just swap drawing's buffers so animation will be smooth and nice. Can I do something similiar in Android or has Android some tricks for optimizing drawing views?
The solution is to use SurfaceView with background thread.
I am trying to capture the screen shot of my android application from onDrawFrame function of my Renderer. But it is dropping the frame and freezing the application till the process is complete. I am trying to do it on a different thread but no success. Is it possible to get the screen shot on a different thread.
You can't perform the glReadPixels() from another thread, because the EGL context can only be current in one thread at a time, and you have no control over it with GLSurfaceView.
However, 95+% of the time spent grabbing a screen shot from GLES is spent on PNG/JPEG compression and disk I/O. So if you make the glReadPixels() call from onDrawFrame(), and then hand the data off to a new thread, you should be able to continue running while the screen shot is processed in the background.
As already mentioned a direct read may be impossible from another thread but there are other ways.
Instead of drawing your scene directly to the surface view you may draw it to a frame buffer object (FBO) with attached texture and then redraw the texture to your main buffer. This is a pretty standard procedure for post processing and such and does not have a high performance impact. To realize this you actually just need to look into how to create the FBO, bind it before the drawing begins and the rest of your code should keep as it is. Then also add the code to redraw the FBO texture on the screen by binding the main buffer (index 0 should do).
For the screenshot on a separate thread you now need to create a new thread and a new context which is set on that thread. The new context must be shared with the main one (I believe there is a constructor that accepts the main context for that) so you may share the texture. Now the fun part: When you want to take the screenshot you need to create a new texture, attach the new texture to the FBO, detach the old texture. By doing so you kind of steal the texture to which the content is drawn and you can do whatever you want with it and on any thread you want. So put it into your secondary thread and on that context you may create another FBO, bind it and read the pixels from it on that thread. Do not forget to cleanup though.
Some caution is advised though. This kind of procedure may be good when you make a relatively small amount of screenshot. If one screenshot is not completely done before another one begins you will inflate in memory usage and your app will most likely crash. So be careful not to do that, create some kind of locking mechanism or limit the number of screenshot processing in progress. And this is not just for openGL, the same issue may occur when simply encoding the image data.
And just a note on your original idea: Even if you could use the surface view on a separate thread and read pixels from its main buffer you may not expect you will get a good result. The buffer may be drawn to while you are reading so it would be possible you would get chunks of data from different frames. Still this is just in theory because the truth is the buffer would simply be locked and your application would crash while trying to access it. So this is in no way possible and even if it was the result would be unpredictable.
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 am working on an android canvas game and have noticed a lagspike just as the main game form is being drawn. It started just after I started sprinkling synchronized(surfaceHandler) around different parts as an attempt to battle concurrent array modification. Did I over synchronize? What is the rule of thumb on when to synchronize and when not to, and when should visible data be modified?
Also is it possible that the spike is caused by something else? The draw method executes while this is happening, but no touch interaction is possible (most, if not all, of the touch method is synchronized).
Advice?
I think that as long as you are generated a canvas from the surface holder in one area, you shouldn't have to synchronize. This may or may not be causing the lagspike. If you are using surfaceHandler in multiple threads, you may want to condense all your drawing into one thread or you will need to keep the synchronize.
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.