1

我对这个有点迷茫。如何获得 OutOfBounds?是否有大小限制(除了 sizeof (int))?

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

java.lang.ArrayIndexOutOfBoundsException at kenyu73.realsignal.DatabaseWrapper.getSignalValues(DatabaseWrapper.java:137) at kenyu73.realsignal.DatabaseWrapper.getSignalValues(DatabaseWrapper.java:116) 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)

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

条形图类

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

数据库包装类

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;
}
4

6 回答 6

2

唯一合理的答案是cursor.getCount()返回的数字低于您的do..while循环进行的循环数。我没有看到do..while循环逻辑中的错误(尽管这是不寻常的逻辑;见下文)。

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

如果您并不真正关心为什么并且只是希望它停止发生,您可以使用 aList代替:

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())是一种方便的循环方式),而不是(再次)我在你do..while的 .的直接性while (cursor.moveToNext())

于 2012-04-04T12:28:35.087 回答
1

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

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

如果以前的不适合你,总有这样的:

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

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

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

于 2012-04-04T14:15:27.240 回答
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();
于 2012-04-04T12:24:49.633 回答
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();
于 2012-04-04T12:28:27.683 回答
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]);
于 2012-04-04T12:35:22.153 回答
0

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

if (cursor.moveToFirst()) {
  do....
}
于 2012-04-04T12:37:02.100 回答