JSON Object repeated unexpectedly in the array

Jimmy :

I am writing an android application recording sensor data. Trying to save these data to json File, but the json array turns out to repeat the item of the array with the most recent measurement.

private JSONObject mSensorState = new JSONObject();
private JSONArray mSensorBuffArray = new JSONArray();

@Override
public void onSensorChanged(SensorEvent sensorEvent) {
  ...
  mSensorState.put("HR",HR_data);
  mSensorState.put("Step",Step_Data);
  mSensorBuffArray.put(mSensorState);
  Log.d(TAG,"JSON "+ mSensorState.toString());
  Log.d(TAG,"JSON "+ mSensorBuffArray.toString());
}

The data for current state 'mSensorState' displace correctly as an json object. updated as expected

JSON {"HR":"95","Step":"10328"}
JSON {"HR":"96","Step":"10328"}
JSON {"HR":"98","Step":"10328"}

But the array doesn't. It was shown as an array of most recent measurement.

JSON [{"HR":"98","Step":"10328"},{"HR":"98","Step":"10328"},{"HR":"98","Step":"10328"},
Izruo :

The invalidation of mSensorState is flawed.

I guess somewhere within the ... omit, there is a

mSensorState.clear();

but it should really be

mSensorState = new JSONObject();

This boils down to the java memory model, which is thoroughly explained here on Stackoverflow. One of the comments there constructed a decent analogy:

Think of mSensorState as a balloon. In java, however, you never actually hold the balloon, but always a string to it. With this in mind, let's look at the call

mSensorBuffArray.put(mSensorState);

First of all, a second string is attached to balloon and passed to the method invocation. During that method, mSensorBuffArray will hold on to the passed string in its most recent index.

Once this method is called again with the same object reference, the same thing will happen again and mSensorBuffArray will hold two string to the same balloon at two different indices. Changes made on that balloon are therefore visible through both indices.

Now, back to

mSensorState = new JSONObject();

This sort of cuts the string you are currently holding and attaches it to a new balloon. The old balloon is not gone, as it may have other string attached. If no strings are left, java will ultimately destroy the balloon at some point in the future.


If applicable, the JSONObject can also be tied to the scope of the method by converting it to a local variable:

public void onSensorChanged(SensorEvent sensorEvent) {
    ...
    JSONObject sensorState = new JSONObject();
    sensorState.put("HR",HR_data);
    sensorState.put("Step",Step_Data);
    mSensorBuffArray.put(sensorState);

If it is required in other methods, the most recent value can still be acquired from the JSONArray: (assuming that it implements List)

private void internalStuff(/*whatever you need*/) {
    JSONObject sensorState = mSensorBuffArray.get(mSensorBuffArray.size() - 1);

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=157012&siteId=1