I'm using the beacon ranging methods to discover and use iBeacons. However, I have run into problem while trying to iterate through all the beacons that were found.
The beacon service returns a collection, which I can check the size of and see there are 3 beacons. However, not matter what I try I can reliably iterate through the beacons. I seem to go in a different random order of beacons every time, and some are frequently skipped over.
I have tried while(iBeacons.iterator().hasNext()) and that just froze my app. I have tried comparing the lastBeacon which I parsed to the current beacon selected and throwing it out, but this didnt work to get through all beacons.
I think that since the collection is being update asynchronously and my parsing takes far longer than a second new beacons have been added before I ever get a chance to process the old ones, and I seems to just randomly process one from the collection each time.
How can I get and parse each beacon each time?
The code is close -- it simply needs to construct an Iterator on a separate line like this:
Iterator<IBeacon> iterator = iBeacons.iterator();
while (iterator.hasNext())
The reason your the freezes has nothing to do with asynchronous updates by the library. (The list of iBeacons passed to the ranging callback is a copy of those seen in the last scan cycle and never gets changed.) The problem has to do with the way the iterator() method works in Java.
In the code above, the while(iBeacons.iterator().hasNext()) creates a new copy of Iterator every time inside the loop, and that iterator is always pointing at the first element in the iBeacons collection. So if there is ever at least one item in that collection when the loop starts, it will never finish, and the code will freeze.
You can demonstrate this with the following example:
public class IteratorTest{
public static void main(String []args){
java.util.Collection iBeacons = java.util.Arrays.asList("1", "2", "3");
System.out.println("This loop will not freeze");
java.util.Iterator iterator = iBeacons.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
System.out.println("This loop will freeze");
while(iBeacons.iterator().hasNext()) {
System.out.println(iBeacons.iterator().next());
}
// We will never get to here
}
}
Which produces the following (never ending) output:
This loop will not freeze
1
2
3
This loop will freeze
1
1
1
1
1
1
1
1
1
1
1
1
1
Related
I need to do nested loops with querying lists instead of looping everything because it causes some memory leaks and crashes in flutter.
which causes a freeze that never ends.
here is an explanation :
I have those classes:
class Station {
String stationName;
}
class Line {
String lineName;
List<station> inLine;
}
Now I have 2 lists of Line and I need to check the for lines that have mutual stations .. here is the code I have used :
List<Station> mutualStations = [];
for (Line singleLine in listNumberOne) {
for (Station inline in singleLine.inLine){
for(line secondLine in listNumberTwo) {
for(station secondInLine in secondLine.inLine){
if (inline.name == secondInLine.name) {
Station instanceOFStation = Station(name: inLine.name);
mutualStations.add(instanceOFStation);
}
}
}
}
}
And for sure this code is a huge memory leak and am sure flutter have an easier way to do it .. anyone can help?
I am not an expert on Flutter, please correct me if I am wrong, but I think this code is running on the UI thread, which is also responsible for rendering the UI element. So, in case the UI thread is busy in the above code, your APP would freeze for some time.
I can't help but notice that your algorithm is of O(n^4), which is very very slow. Considering the list contains 10 lines with each one containing 10 stations, the loop will iterate through 10^4 times i.e. 10,000 times.
Also, in case there are 50% matching stations, then you are creating around 5,000 objects inside the loop, since you haven't checked whether the stations are duplicate or not.
One of the optimization I could provide is create two different set of station name. And then loop over them to determine the mutual stations.
So, to create the Set you would loop with O(n^2) twice and then loop once over the set O(m) [ m -> Number of stations in the Set].
So considering worst case, we would get all station name as unique, which would be resolved as follows:
2 * O(n^2) + O(m) => 2 * 100 + 200 => 400 iterations
Which Optimise the time and memory consumption by 96% (From 10,000 iterations to 400 iterations). Which reduces the load on UI thread and make your app responsive to the user. Also, by avoiding that much amount of object allocation, you save your app from Memory leak.
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 am writing an OpenGL game and have a list of objects to render in the rendering loop, at the same time, updates from the server update this list of objects to render in a asynchronous task.
If I pause the rendering of the objects while the array gets updated obviously you see that on screen.
Would making a copy of the list, updating that and then copying it back (pause the render) be the best way?
Try the CopyOnWriteArrayList, which is a thread-safe version of ArrayList, which makes it possible to add elements to the list while traversing it.
A CopyOnWriteArrayList will allow multiple threads to access the list at once, as #Egor suggested, but I'm not sure it'll be fast enough.
Both reader and writer will interfere with each other all the time, and your users might notice it.
Give it a try. If it works - great, if not, you should have three copies of the list - one the reader (your rendering loop) accesses, one waiting for the next iteration of the rendering loop and another updated by the writer (the server update thread).
Use the three lists like so:
List<info> _readerList, _waitingList, _writerList;
In your rendering loop:
while(true) {
if(_waitingList!=_readerList)
_readerList = _waitingList
render list
}
In your service update thread:
while(true) {
read data from server
update _writerList
if there were updates {
_waitingList = _writerList
}
}
Before you start rendering, initialize _waitingList and _writerList to be two different lists with the same content, and start the loops.
This way you have no locking at all, and your two threads don't interfere with each other. The only point of contact between the two threads is the _waitingList reference, and both threads change that in one atomic operation.
The down side for this is that you'll have to wait until both the render loop and the server thread complete an iteration before the user sees the result.
CLARIFICATION:
It just occured to me that I missed an important point -the writer should create a new list and not reuse the same instance, otherwise after a couple of iterations both reader and writer will use the same list, and you're back to the same old race condition.
I am working on an android project and found that an operation becomes bottleneck in performance. This operation works on a large array A and stores the result into another array B.
I found that this operation can be parallelized. The array A can be divided into N smaller segments. The operation can work on each segment independently and store the result into a corresponding segment in B.
The operation is written in native code with GetPrimitiveArrayCritical/ReleasePrimitiveArrayCritical pairs to access array A and B.
My question is that if using multi threading, GetPrimitiveArrayCritical(pEnv, A, 0) will be called multiple times from different threads. Does GetPrimitiveArrayCritical block? i.e. if one thread makes this call, can a second thread make the same call before the first one calls ReleasePrimitiveArrayCritical()?
Please help.
Yes, you can call GetPrimitiveArrayCritical() from two concurrent threads. The function will not block, and your two threads will grant access to the underlying array to native code. But on the other hand, the function will do nothing to synchronize this access, i.e. if thread 1 changes the value at index 100, and thread 2 also changes the value at index 100, you don't know which will be chosen at the end.
If you don't write to the array, you are guaranteed to be served correctly. Don't forget to ReleasePrimitiveArrayCritical with JNI_ABORT flag.
If you want to write to the array, check the output parameter isCopy as set by GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy). If the result is 0, you can safely proceed with your multithreaded approach.
If the result is not 0, ReleasePrimitiveArrayCritical() will overwrite all elements of the Java array, even if some of them was changed in Java or in C on a different thread. If your program detects this situation, it must release the array (with JNI_ABORT) and wait for the other thread to complete. On Android I have never seen an array being copied, they are always locked in-place. But nobody will guarantee that this will not happen to you, either in a current system or in a future version.
That's why you MUST check isCopy parameter.
I have a test case for my app which fills in the TextViews in an Activity and then simulates clicking the Save button which commits the data to a database. I repeat this several times with different data, call Instrumentation.waitForIdleSync(), and then check that the data inserted is in fact in the database. I recently ran this test three times in a row without changing or recompiling my code. The result each time was different: one test run passed and the other two test runs reported different data items missing from the database. What could cause this kind of behavior? Is it possibly due to some race condition between competing threads? How do I debug this when the outcome differs each time I run it?
Looks like a race condition.
remember in the world of threading there is no way to ensure runtime order.
I'm not an android dev so I'm only speculating but UI is only on one event thread generally so when you call the method from another thread (your test) you're probably breaking that as you're outside of the event thread.
You could try using a semaphore or more likely a lock on the resource.
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/Lock.html
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Semaphore.html
I (finally!) found a solution to this problem. I now call finish() on the tested Activity to make sure that all of its connections to the database are closed. This seems to ensure consistency in the data when I run the assertions.
I would suggest making a probe for the database data rather than a straight assert on it. By this I mean make a piece of code that will keep checking the database for up to a certain amount of time for a condition rather than waiting for x seconds (or idle time) then check, I am not on a proper computer so the following is only pseudo code
public static void assertDatabaseHasData(String message, String dataExpected, long maxTimeToWaitFor){
long timeToWaitUntil = System.getCurrentTimeMillis() + maxTimeToWaitFor;
boolean expectationMatched = false;
do {
if(databaseCheck() == dataExpected){
expecttionMatched == true;
}
}while(!expectationMatched && System.getCurrentTimeMillis() < timeToWaituntil);
assertTrue(message, expectationMatched);
}
When i get to a computer i will try to relook into the above and make it better (I would actually of used hamcrest rather than asserts but that is personal preference)