我在这一点上有点失落。我如何获得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;
}
答案 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....
}