I m writing an app containing an asyncTask which continuously (every seconds or so) adds a value to an ArrayList<Float> (declared static).
The value is a measure in inches that I want to plot.
In order to do that I have implemented a solution with OpenGL ES.
And every time I add a new value my AsynTask calls the requestRender() method.
Then the drawRenderer() take the ArrayList<Float> and draw lines with it.
At this point everything works perfectly fine.
I also want that the user can pinch-zoom and move the plot. So I have a TouchsurfaceView which also calls requestRender() when needed.
Most of the time it works, but time to time I get an error because of concurrent requests for the ArrayList<Float> (almost sure of that).
Any ideas How can I solve this ? I see lock and synchronized stuff, but can t find how to properly use them for my case.
Thanks for reading me.
put all the updates to the static variable in a synchronized static method and use only that for making updates.
Related
The way I understand the HERE Android SDK is that there's a MapView that has a backing Map object. Adding objects, setting the center, zooming etc should be performed on the Map object and this eventually reflects on the MapView.
Question:
Are there any restrictions on what thread the operations on the Map object must be performed? For example, must they all be called on the UI thread? Also, should multiple subsequent calls be synchronized?
I ask this because I want to make multiple changes in a Map (resize the map view, change some visible layers, change the scheme, add a MapRoute and zoom out to the bounding box of the route). When I try this, it sometimes works but sometimes doesn't. Sometimes, only some of the operations are applied. For example, everything works except the zoom is not applied.
I know there are some listeners that can help me:
Map.OnTransformListener - this I can use to let me know when a zooming operation has ended
Map.OnSchemeChangedListener - this I can use to know when a scheme change event has ended
What is not clear to me from the documentation is what other operations constitute a "transform"? Which of these operations must be performed in a synchronized fashion?
For example, is the following code expected to behave correctly?
map.setCenter(coordinate, Animation.BOW, 18, 0f, 60f);
map.addMapObject(routeObject);
map.setVisibleLayers(layersToShow, true);
map.setScheme(Map.Scheme.NORMAL_DAY)
Note that in the above example, I'm proceeding to make changes immediately after setCenter even before the animation is complete. Is this the expected way to use the API?
There is no restriction on what thread you call the API from. Internally, all calls are synchronized and thread safe.
What you are looking for is the MapView#executeSynchronized API. [link] This will batch up a few operations into one screen redraw. [At least when I wrote that API a few years ago]
What you are experiencing happens because the underlying rendering thread started drawing some of the commands from the calling thread. This caused subsequent calls to lose effect.
I am trying to incorporate Android GraphView project into my app and all the time I have some strange problem with it.
My app requires drawing graph from real time data. I have thread with all the communication that is providing the data. In main thread I am reading this data and simply use mSeries1.appendData(new DataPoint(counter,data[0]),true,100); where counter is int that is incremented after each update.
Unfortunately at some point it freeze. I've tried putting it in synchronized block or changing the line of code to mSeries1.appendData(new DataPoint(counter,counter),true,100); and still this same result.
This is how the memory looks like during app running and when it freezes:
Does anyone have any idea what might be wrong in here?
EDIT:
This is my current method for updating my graph view:
public void onEventMainThread(ReadingsUpdateData data) {
mSeries1.appendData(new DataPoint(counter,data.getData()[0]),true,100);
counter++;
}
Maybe it's too late, but I had the similar problem and finally I found that when GraphView is appended a new data of "NaN" freezes.
So check the situation in which the result will be NaN such as divide by zero or something like that.
Although you do not specify the rate at which you add points, and how long for the app runs without crashing, you should expect things to go wrong at some point (you're potentially generating an infinite number of point objects, while the memory is indeed limited).
Do you need to have all the points the app has received from the beginning drawn ? If not, you could implement a sort of circular buffer that only keeps the X last values generated by your "provider thread", and update the graph each time you receive a new value with the method
your_series.resetData( dataPoint[] my_circular_buffer_of_data_points );
This thread is quite similar to your problem, have a look at it !
I have an infinite loop in my Render Thread. I tried measuring assuming that every call to eglSwapBuffers draws a new frame, but that is giving me results like 200 fps, which is not possible, right? The refresh rate cannot exceed 60?
Now I am doing the same thing but also using surfaceTexture.getTimeStamp() of the surfaceTexture of the SurfaceView. I consider a frame as having been drawn only if the timestamp returned in the previous iteration is not the same as in the current. Is the an acceptable way to measure? This is showing 50-55fps when I do no drawing. ie the loop has only eglSwapBuffers() and the getTimeStamp calls.
The surfaceTexture.getTimeStamp() seems to be giving the correct result. I tested it by adding up all the differences between results returned by consecutive getTimeStamp() calls and it is equal to the total time the code ran for. This indicates that no frames are being left unconsidered etc.
Another solution I found is this Android app. I do not know how it works but it is giving approximately the same results as the above method.
I'm building an Android app with a simple 3D engine. It was working earlier, but was incredibly messy. I've refactored the heck out of it, but I did little to the 3D engine. Now I'm running into a very strange problem where calling translatef within the draw() method (which itself is called from within onDrawFrame within the class that implements GLSurfaceView.Renderer) does not use the current value of the x/z float variables, which are scoped to the class. I cannot explain it. There is zero code that would reset them to their initial values, but that's what is happening. The only time these variables are touched are when the class is instantiated (done once, never touched again), when they change due to user input (verified as accurate with the debugger at every point possible), and when translatef is called, at which point they are only read.
The thing is, they are always the initial value that was passed to the constructor when read by the translatef method, but are accurate otherwise at any other point in the class when they are used or altered. If, say, we set z to z + 1, it remains at that value regardless of the value read by translatef. What gives? I'm at a loss as to why the draw() and/or translatef() methods are somehow sticking to the original values and not reading the modified values. I'm utilizing GL ES 1.0 and Android 2.2 as my testing platform.
There's too much to just dump it all here, but this should be sufficient to get the problem across:
private float movex, movez;
public GLEngine(){
//The values are set in the constructor and are accurate at this point.
movex = Controller.getX();
movey = Controller.getZ();
}
public void move(float x, float z){
//Again, debugging in here shows that the values are being set properly.
movex = x;
movez = z;
}
public void onDrawFrame(GL10 gl){
//Debugging anywhere within this method shows only the values for movex and
//movez that were set in the constructor.
...
gl.translatef(movex, .5f, movez);
...
I got a tip to make movex and movez volatile as this was likely related to threading issues (although I have not explicitly declared any threads here), but that didn't help.
As both values are held outside the class, I was able to make this work by pulling them from the controller in the onDrawFrame method, but this requires the variables to be pulled and additional operations to be performed on them on every draw, which is costly. There has to be a better way...
Since x and z are private variables, it should be easy to track down.
You are only ever setting them via your move method. To find this out, delete or comment out your move method (temporarily) and do a save. Eclipse will highlight any code that is now broken as a result.
Once you are sure that all changes for x and z are going through the move method, set a breakpoint there. (You can set conditional breakpoints as well).
If you stop at a breakpoint, you can can see which method called move.
This should let you track the problem down.
I use opengl to draw values from an array. The values are from the 3 Android sensors. I want to turn of the renderer during I collect the values. It seems that drawing and gathering at the same time have differenet results, so I want to turn off rendering while I gathering sensorvalues. At the moment I use a boolean in the ondraw() to stop drawing. But is there a better way to do this? There happen freaky things when I stop drawing , like the stuff I draw jittering a little bit some times, but it can't be because there are no drawing( ondraw(){ if(boolean){.........}}
Thank you so much for your help :-)
You can ask GLSurfaceView to only draw when asked via setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY), then call requestRender() when you're ready to draw.
I have a suggestion: Create a thread to collect the sensor data, and make it available as an object. This thread would gather all the data, and synchronize on the public value object. Blocking time would be minimized.
collectLocalData = getData();
synchronized(pubData) {
pubData.set(collectLocalData);
}
Your render thread can then Do the same when copying the public values for local consumption.
synchronized(pubData) {
renderLocalData.set( pubData );
}
renderData( renderLocalData );
If polling the sensors takes longer than rendering time, the same data will be rendered more than once. The animation might get a little twitchy, but no more so than what the data represents.
PS: your jitters may be a result of the data itself rather than your code.