ArrayIndexOutOfBoundsException错误......为什么?

时间:2012-04-04 12:19:11

标签: java android

我在这一点上有点失落。我如何获得OutOfBounds?是否有大小限制(除了sizeof(int))?

也许是因为多线程可以来这里? UI线程和服务线程?

  

java.lang.ArrayIndexOutOfBoundsException at   kenyu73.realsignal.DatabaseWrapper.getSignalValues(DatabaseWrapper.java:137)at at   kenyu73.realsignal.DatabaseWrapper.getSignalValues(DatabaseWrapper.java:116)at at   kenyu73.realsignal.BarScaleGraph $ buildGraphThread.drawGraph(BarScaleGraph.java:128)   在   kenyu73.realsignal.BarScaleGraph $ buildGraphThread.execute(BarScaleGraph.java:94)   在   kenyu73.realsignal.BarScaleGraph $ buildGraphThread.run(BarScaleGraph.java:74)

另外,我正在使用静态实例调用此类方法。我在想线程正在竞争相同的变量???想法?

BarScaleGraph类

ContentValues[] values = DatabaseWrapper.getInstance().getSignalValues(getContentResolver(), signal_type, false);

DatabaseWrapper类

private static final DatabaseWrapper    instance    = new DatabaseWrapper();

// grab static instance so we only have one db wrapper
public static DatabaseWrapper getInstance() {
    return instance;
}

. . . .

public ContentValues[] getSignalValues(ContentResolver cr, int signal_type_id, boolean bGroupByLatLon) {

    String sWhere = "signal_type_id=" + signal_type_id;

    Cursor cursor;

    if (bGroupByLatLon) {
        cursor = cr.query(CONSTS.CONTENT_URI_GRP_LATLNG, null, sWhere, null, null);
    } else {
        cursor = cr.query(CONSTS.CONTENT_URI_LOGGER, null, sWhere, null, null);
    }

    ContentValues[] values = new ContentValues[cursor.getCount()];

    int count = 0;
    if (cursor.getCount() > 0) {
        cursor.moveToFirst();
        do {
            values[count] = new ContentValues(); // <--- LINE 137
            values[count].put("signal_value", cursor.getInt(cursor.getColumnIndex("signal_value")));
            values[count].put("latitude", cursor.getInt(cursor.getColumnIndex("latitude")));
            values[count].put("longitude", cursor.getInt(cursor.getColumnIndex("longitude")));
            values[count].put("timestamp", cursor.getLong(cursor.getColumnIndex("timestamp")));
            values[count].put("network", cursor.getString(cursor.getColumnIndex("network")));

            count++;

        } while (cursor.moveToNext());
    }
    cursor.close();

    return values;
}

编辑:尝试此操作 - 将同步添加到实例

// grab static instance so we only have one db wrapper
public static synchronized DatabaseWrapper getInstance() {
    return instance;
}

6 个答案:

答案 0 :(得分:2)

唯一合理的答案是cursor.getCount()返回的数字低于do..while循环所产生的循环数。我没有在do..while循环的逻辑中看到错误(虽然这是不寻常的逻辑;见下文)。

我的猜测是它是一个实时光标,而其他东西是删除在循环运行时添加相关行。找出答案的唯一真正方法是在代码中添加检测,这样您就可以看到cursor.getCount()返回的内容,每个循环迭代开始时的count等等。

如果你真的不关心为什么而只是希望它停止发生,你可以使用List代替:

public ContentValues[] getSignalValues(ContentResolver cr, int signal_type_id, boolean bGroupByLatLon) {

    String sWhere = "signal_type_id=" + signal_type_id;

    Cursor cursor;

    if (bGroupByLatLon) {
        cursor = cr.query(CONSTS.CONTENT_URI_GRP_LATLNG, null, sWhere, null, null);
    } else {
        cursor = cr.query(CONSTS.CONTENT_URI_LOGGER, null, sWhere, null, null);
    }

    List<ContentValues> values = new LinkedList<ContentValues>();
    ContentValues entry;

    while (cursor.moveToNext()) {
        entry = new ContentValues();
        entry.put("signal_value", cursor.getInt(cursor.getColumnIndex("signal_value")));
        entry.put("latitude", cursor.getInt(cursor.getColumnIndex("latitude")));
        entry.put("longitude", cursor.getInt(cursor.getColumnIndex("longitude")));
        entry.put("timestamp", cursor.getLong(cursor.getColumnIndex("timestamp")));
        entry.put("network", cursor.getString(cursor.getColumnIndex("network")));
        values.add(entry);
    }
    cursor.close();

    return values.toArray(new ContentValues[values.size()]);
}

(或代码就是这样。)

我使用了临时链表,所以我不关心cursor.getCount返回什么,在完成后将其转换为数组。我还使用了更常见的习惯来循环游标(因为游标在第一行之前开始,while (cursor.moveToNext())是一种方便的循环方式),而不是(再次)我在你的{{中看到了一个逻辑错误1}},但我喜欢do..while的简单性和直接性。

答案 1 :(得分:1)

我猜这是一个竞争条件,其中计数是线程之间的变化...尝试同步方法:

public synchronized ContentValues[] getSignalValues(...){
    ...
}

如果前一个不适合你,总会有:

public ContentValues[] method1(...){
    synchronized (monitor1) {
        ...
    }
}

public ContentValues[] method2(...){
    synchronized (monitor2) {
        ...
    }
}

这可以解决问题,但我会尝试使用不同的架构来阻止这种方法。

答案 2 :(得分:0)

这个怎么样,

int count = 0;
if (cursor.getCount() > 0) {
ContentValues[] values = new ContentValues[cursor.getCount()];
cursor.moveToFirst();
do {
        if(cursor.getCount() >= count)
        {
        values[count].put("signal_value", cursor.getInt(cursor.getColumnIndex("signal_value")));
        values[count].put("latitude", cursor.getInt(cursor.getColumnIndex("latitude")));
        values[count].put("longitude", cursor.getInt(cursor.getColumnIndex("longitude")));
        values[count].put("timestamp", cursor.getLong(cursor.getColumnIndex("timestamp")));
        values[count].put("network", cursor.getString(cursor.getColumnIndex("network")));
        }
        count++;
    }  while (cursor.moveToNext());
  }
cursor.close();

答案 3 :(得分:0)

你使用do ... while循环,do while循环将执行额外的迭代,因为在每次迭代后检查条件,而不是之前。代码超过你的保护条件并进入循环,然后在有一个结果时执行2x。

将循环切换到while循环,这应该可以正常工作。

int count = 0;
    if (cursor.getCount() > 0) {
        cursor.moveToFirst();
        while (cursor.moveToNext()) {
            values[count] = new ContentValues();
            values[count].put("signal_value", cursor.getInt(cursor.getColumnIndex("signal_value")));
            values[count].put("latitude", cursor.getInt(cursor.getColumnIndex("latitude")));
            values[count].put("longitude", cursor.getInt(cursor.getColumnIndex("longitude")));
            values[count].put("timestamp", cursor.getLong(cursor.getColumnIndex("timestamp")));
            values[count].put("network", cursor.getString(cursor.getColumnIndex("network")));

            count++;

        }
    }
    cursor.close();

答案 4 :(得分:0)

虽然我不确定问题是什么,但你可以用更安全的方式做到:

List<ContentValues> values = new ArrayList<ContentValues>();
if (cursor.getCount() > 0) {
    cursor.moveToFirst();
    do {
        ContentValues value = new ContentValues();
        value.put("signal_value", cursor.getInt(cursor.getColumnIndex("signal_value")));
        values.add(value);
    } while (cursor.moveToNext());
}
// ...
return values.toArray(new ContentValues[0]);

答案 5 :(得分:0)

cursor.moveToFirst可能返回false。尝试将其包装在if语句中:

if (cursor.moveToFirst()) {
  do....
}