Jon W. Jones
Jon W. Jones

Reputation: 79

ArrayList<SensorEvent>.add(...) begins overwriting values

I am writing an app that needs to keep the values that come from the accelerometer. I am doing this by using an ArrayList and then when onAccelerationChanged(...) gets called I simply add those values to the list. The problem is that after so many values (never consistent) get pushed into the list it starts overwriting the values with the value I am adding. I figured I was doing something stupid so I took the 'Accelerometer Play Sample' and modified onSensorChanged(...) to do the same. Doing this replicates the issue.

variable added to class:

private ArrayList<SensorEvent> _accelData = new ArrayList<SensorEvent>();

onSensorChanged:

@Override
public void onSensorChanged(SensorEvent event)
{
  if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER)
    return;

  Log.e("Event to Add", event.timestamp + ", " + event.accuracy + ", " + event.values[0] + ", " + event.values[1]
      + ", " + event.values[2]);

  _accelData.add(event);

  if (_accelData.size() > 25) {
    for (SensorEvent tmp_event : _accelData) {
      Log.e("Events in list", tmp_event.timestamp + ", " + tmp_event.accuracy + ", " + tmp_event.values[0] + ", "
          + tmp_event.values[1] + ", " + tmp_event.values[2]);
    }

    _accelData.clear();
  }
}

On the left is each event that was supposed to be added and on the right is the list printed out after 26 adds were performed. As you can tell the values that were supposed to be added don't match the list itself and there is a ton of repetition of the last and second to last value in the list.

enter image description here

I fixed this by making a new class that takes in an event and copies those values. Then I make the ArrayList take that class instead. It works but I don't understand why and was hoping someone could educate me since I am new to Java and Android.

Upvotes: 3

Views: 491

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1500805

This is documented:

NOTE: The application doesn't own the event object passed as a parameter and therefore cannot hold onto it. The object may be part of an internal pool and may be reused by the framework.

By adding a reference to a list you're doing exactly what you're told not to.

Basically the framework is repeatedly passing you a reference to the same object, changing the values within the object each time.

If you need to hold on to the different values, you'll need to copy them into your own object and add that reference to your list (or clone the value you're passed into another SensorEvent if you want).

Upvotes: 5

Related Questions