I am interested in creating a 2D drawing application for Android using touch input. I will be using a SurfaceView to accomplish this as it is the most efficient next to OpenGL, but for this application, it should now be an issue.
After reading the documentation and overview (http://developer.android.com/guide/topics/graphics/2d-graphics.html) of SurfaceView and Canvas drawing, it seems they recommend creating an inner class which extends Thread to handle the work for drawing.
This makes sense of course as to not lock up UI and offload the work to a secondary thread. However, I am unsure why they do not use an external class which extends Thread, or even better, why not use a Runnable that is external?
Is there a benefit to leaving this as an inner class? And is there a benefit to extending Thread as opposed to implementing Runnable for Canvas drawing?
Thanks!
Well in their scenario they got one thing right and one thing wrong IMO:
The decision to make the thread class an inner class is ok, because that class is only required in that particular part of the code, so no need to expose it to the outside.
I don't really agree with extending Thread. The best practice is to implement Runnable and override the run method. This is because you can use that Runnable in several different ways, like starting a normal thread, queuing it up in a thread pool, etc. It also allows you to extend a different class if you need, since Runnable is just an interface.
Related
I'm writing a simple tilting game. Make a ball roll over the screen in the direction you tilt your phone.
So I downloaded an example on how to get the sensor data and that works fine (I use a rotation matrix to avoid the Euler angle problem). But then I tried to put it into a bigger app and I have some trouble getting it to work.
My first idea was to run the tilt sensor in a separate thread but
my class: public class TiltSensor extends Thread implements SensorEventListener
is not working to well.
I get one round of values then it stops.
How would you implement this app?
I don't want to block the UI thread so I'm thinking I need a separate thread (GameHandler) to run the game and then I call runOnUithread and from there invalidate the View. I'd also separate the board representation from the View so I'd represent the screen as a matrix and then the view would use that matrix to know how the screen should look.
But I am unsure what the best way to implement the TiltSensor. Should it run in a separate thread or the same thread as the GameHandler? How do I make sure the SensorManager actually calls the onSensorChanged in the GameHandler thread?
In my humble experience, you should:
A) Register your SensorListener on your main thread normally, but make it spawn two (or as needed) WorkerThreads on its constructor.
B) Get the looper reference of both threads, to keep them alive waiting for future requests.
B) Listen to your onSensorChanged on your main thread normally, but do NOTHING OTHER (this is important) then delegate a copy of the values to a new runnable object that will process your game logic.
C) Enqueue your new runnable object on your WorkerThread looper reference accordingly.
D) Make the runnables (that are already off your main thread) do what they have to do and synchronize changes to a singleton that may be consulted by who is interested in updating your views.
When controlling OpenGL from other threads, if it is GLSurfaceView, we use queueEvent(). Then, in cases where OpenGL is created on SurfaceView (use eglCreateWindowSurface, eglMakeCurrent, etc.), how should I implement for operating OpenGL from other threads?
You can implement your own queueEvent.
Make a queue. (ArrayList<Runnable> mQueue)
queueEvent() adds Runnable instances to this queue(mQueue).
Your SurfaceView's rendering thread pops event from the queue.
invokes event.run()
Use locks (synchronized or explicit locks) to avoid problems.
In GLSurfaceView, there are 3 and 4 steps in a loop of GLThread and mQueue is protected by synchronized blocks.
see also: GLSurfaceView
PS: sorry for my poor english.
I have create a screen with two kind of views : normal view (buttons to receive up/down action ) and surfaceview. The SurfaceView implements SurfaceHolder.Callback and run on another thread and have a method name Tick().
When those buttons receive action, they will call method Tick(), and I want this method will run same thread with SurfaceView (for synchronize purpose), but don't know how to.
Please give me some idea for my issues.
Thanks :)
If you really want to run Tick() method in separate thread which also draws on the surface you can use HandlerThread for it. So you will be able to create Handler for it and post runnables which will be executed in this thread. But this also will put some restrictions on your drawing routine - you need to prevent it from sleeping or waiting because thread need to process message queue.
But actually I suppose any other reasonable way of synchronization will be easier than running this method on the same thread.
What is better for a android game to use:
a SurfaceView with a rendering thread
or
a SurfaceView with a thread that calls the SurfaceView function doDraw()
Thanks.
The drawing in a SurfaceView is already handled in a separate thread. You do not need to spawn a new one.
See the API doc about it:
One of the purposes of this class is to provide a surface in which a secondary thread can render into the screen. If you are going to use it this way, you need to be aware of some threading semantics:
All SurfaceView and SurfaceHolder.Callback methods will be called from the thread running the SurfaceView's window (typically the main thread of the application). They thus need to correctly synchronize with any state that is also touched by the drawing thread.
You must ensure that the drawing thread only touches the underlying Surface while it is valid -- between SurfaceHolder.Callback.surfaceCreated() and SurfaceHolder.Callback.surfaceDestroyed().
I am using Eclipse to develop an Android application that plots Bluetooth data.
I am using open source code, which has an existing solution that I want to extend and not replace to solve my development problem as stated above.
The open source code has a very nice and solid background thread that among other things continually logs BluetoothData to logcat even when I switch to a new activity.
Currently I have a solution which I am concerned about: I simply leverage a background thread method that writes to logcat to call a static plotData() method in my Plotting Activity. The result seems good. I get a nice plot. It clips along in real-time. Looks like an oscilloscope.
But I have received negative feedback about using the existing background thread coupled with a static method to plot the BluetoothDate. It has been suggested that I use a new thread, or add a handler, or use Async Task, or AIDL to solve my problem.
I have looked at all these solutions without success. Nothing seems to work like my static plotData() method. That is to say the existing background thread calls my static plotData() method which results in a real-time plot that looks great.
But I am still concerned about the negative feedback. I simply want to extend my existing background thread solution which I have done by having it call a static method to plot the data.
What are the problems I might face with this approach? Thread safety? Deadlock? I don't know.
Why do people keep suggesting that I create a new thread, handler, Async Task, or Service to solve my problem when extending my existing thread to call a static method seems to work just fine?
Any suggestions? What are the problems with extending the existing thread to use a static method to plot the data in real-time?
Anyone who says that you should use AIDL for this is a loon who should not be listened to. :) Also someone saying you need a Service if you don't want to have your background thread running when the user is not viewing your activity.
I'm not sure what you mean by "writes to logcat to call a static plotData()." You should write to logcat only for testing. Writing to logcat doesn't cause a call to any Java method.
If you are calling a static plotData() method on your Activity, you need to be extremely careful with this: first because it is difficult to figure out what activity instance should be called from there (it may go away at any time from the user finishing it, or be recreated as a new instance when the configuration changes, etc); and second because you can't touch your app's UI/view hierarchy from a background thread without risking that you corrupt its state (since the view hierarchy is single threaded).
The general model one does for this kind of thing is to have a background thread doing some work, generating the next data to display. Once it is done with the work you send a message to the main thread to have it display the new data. AsyncTask can be a simple way to do this, it takes care of the underlying message sending and threading. You can also implement this yourself, at some point having a Handler that you post a Runnable on or send a Message to that once executed on the UI thread will update your view state.
(Of course if you are using a SurfaceView, the whole point of that is to allow drawing to it outside of the main UI loop, so your background thread could just draw directly on to it as needed. Basically that is like writing a game.)