In Android, I am using a SurfaceView. It is inside a FrameLayout, to draw a couple of things on a transparent layer over the top of a general XML layout (with standard textViews, buttons etc.) The drawing does not involve very intensive computation, and does not animate, it only updates in response to button presses.
All the examples I have seen of SurfaceView use a separate thread for drawing, and then close down that thread in OnSurfaceDestroyed.
My code works without using a separate thread, but it does crash/freeze occasionally, especially when switching between orientations/applications.
So my question is, do I need to use an extra thread to prevent these crashes. And if not, is there any other specific thing I should do in OnSurfaceDestroyed? (I'd rather not post all my code here, just looking for a simple yes/no response and reasons in a couple of sentences).
You don't need to have a separate thread, but it's often a good idea.
For example, take a look at Grafika's "multi-surface test" Activity. It has three overlapping SurfaceViews that are rendered from the UI thread. If you click on the "bounce" button, it starts a new thread to control the animation, because it's simpler to do that way (it can sit in a loop and draw, instead of having to post timed draw events to the UI looper). The bounce thread stops when the Activity is paused. Note the code doesn't do anything in surfaceDestroyed().
The interaction between SurfaceView and the Activity lifecycle can be tricky. A discussion can be found here.
(It can be tricky to get everything right.)
Related
So I understand that any changes to the UI need to be on the main thread for an Android application. And also, you should use other threads to do work so that the UI doesn't freeze up. But some of the work I want to do is preparing UI elements which will be shown later on. I want to get those things ready on a separate thread and then enable a button once its done - that way the user won't be able to access it until it's ready BUT they'll be able to use the main page quickly.
Exactly what operations count as changing the UI? I want to do as much preparation in the background so that the first part of the app ready can be shown ASAP while other parts are still loading.
For example, it seems like findViewById is fine, but what about creating/modifying Views, setting listeners, setId, setEnabled and so on? If I newly create a Button which hasn't been added to a parent, can I setText on it in a background thread?
I am working on a game and I am stumped on how to update my TextView that holds the score. In my Activity I have a TextView for the score and a GLSurfaceView. When the user gets puts in the game I want to be able to update the TextView in the same Activity.
I have tried using inflaters and Casting to type Activity as well as a few others. I know it should be possible however I cannot figure out how to achieve this.
It's a bit unclear why you're having trouble. You should be able to update the TextView as you would in any other Activity, whether or not a GLSurfaceView happens to be present. You just have to make sure that you issue the updates from the main UI thread, not the GLSurfaceView renderer thread. An easy way to do this is to post a message to a Handler on the UI thread's Looper.
One example is Grafika's "record GL app" Activity. It uses a plain SurfaceView, rather than a GLSurfaceView, but the idea is the same. The renderer thread periodically posts messages to the main UI thread with the current frame rate, which is placed in a TextView.
I m new in android.
i have a little bit confusion in SurfaceView and View......
According to my knowledge..
Views are all drawn on the same GUI thread which is also used for all user interaction.
I want to knw is it possible to create separate thread for the handling
Depends on what you define in handling.
If in handling you mean doing calcualtions, downloads etc. then yes.
If by handling you mean splitting control and view up, then no.
If your handling means that handling GUI things in other than GUI thread then Its not possible as Views are coupled with GUI thread or Android Component Activity. But non GUI threads alive even when your activity is finished , and It may leak the references to views. So it has been avided in al most all Programming models. Suppose if you are downloading the some values in Non GUI thread and then update your GUI views and in bwteen your screen orientation takes place and Your activity and its views are recreated but Non GUI thread is till now keeping the reference to old views . This can create old views to not to be collected by Garbage Collector and leak memory .
I'm reading up on SurfaceView and how to use it, and I've come across some information that states that a SurfaceView has View#willNotDraw() set to false by default, and that it's up to you to call SurfaceView#onDraw(). I also read that RomainGuy said that this is done by default because it is more efficient. My question now is, when should you handle calling SurfaceView#onDraw() in a separate thread, and when should you just set View#willNotDraw() to true, and just call SurfaceView#invalidate(). Is there a difference between the two, and does one improve performance more than the other?
See:
http://developer.android.com/reference/android/view/View.html#setWillNotDraw(boolean)
I'm not sure where you got your information, but at least the javadoc says that most users will set this to false to get Android to send it onDraw events itself. As for your question about when you should do this, I would say it comes down to why you're using a SurfaceView.
If your view is displaying something dynamic (e.g. for a game or something that has a tight event loop), you'll want to be controlling exactly when updates happen, especially if you'll have the information to use one of the more detailed forms of invalidate to save redrawing the entire View. You won't want Android to call invalidate for you, and that's why the flag is there.
If, on the other hand, you are simply drawing something static, it makes sense to let Android's UI stack control the invalidations.
By the way, invalidate only posts a request to re-draw the View, so be aware of this if you intend to use the event-loop style (onDraw will be called sometime after you call it).
Edit: some clarifications.
Using SurfaceView.onDraw() and SurfaceView.invalidate() will make SurfaceView behave like a normal View and you will pay for the extra overhead associated with SurfaceView. If you want to draw from the UI thread, use a regular View instead. It's easier and cheaper.
I am making an interactive walkthrough for one of my apps, and in a couple of spots an alpha animation and some various other UI changes (such as checkbox pressed states) would be really great.
The walkthrough has a back and next button. The basic idea is that the next button would start the animation (maybe as a thread?), and if at any point in the animation the back button was pressed, that the animation would stop.
I have looked into the built in Android animation library, but have sort of seen a lot left to be desired. My next thought was a thread, but I know I can't change the UI from an outside thread. Also I want to leave the UI thread open for my back button listener.
Any thoughts on how these simple animations could be achieved?
You're right you can't update UI elements directly from another thread. But you can do this indirectly with Handlers. Handlers are basically a type of IPC that allows you to queue up messages to the UI for proceessing. So what you do is basically create a Handler in your Activity and pass this handler to your process thread. When there's something you want to update in the UI from the process thread just do mHandler.sendEmptyMessage(UPDATE_SOME_VIEW).
Take a look at handlers here.