1

私はこれで少し迷っています。OutOfBounds を取得するにはどうすればよいですか? サイズ制限はありますか (sizeof (int) 以外に)?

複数のスレッドがここに来る可能性があるためでしょうか。UIスレッドとサービススレッド?

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

6 に答える 6

2

唯一の合理的な答えは、ループが作成cursor.getCount()するループの数よりも少ない数を返すことdo..whileです。ループのロジックにエラーは見られませんdo..while(通常とは異なるロジックですが、以下を参照してください)。

私の推測では、それはライブ カーソルであり、ループの実行中に他の何かが関連する行を削除して追加していると思われます。実際に確認する唯一の方法は、コードにインストルメンテーションを追加してcursor.getCount()、何が返さcountれたか、各ループ反復の最初に何があったかなどを確認できるようにすることです。

理由をあまり気にせず、それをやめさせたい場合は、List代わりにa を使用できます。

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

cursor.moveToFirstがfalseを返す可能性があります。それをifステートメントでラップしてみてください。

if (cursor.moveToFirst()) {
  do....
}
于 2012-04-04T12:37:02.100 に答える
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

これはどうですか、

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 ループは余分な反復を実行します。これは、条件が反復前ではなく反復ごとにチェックされるためです。コードはガード条件を通過してループに入り、結果が 1 つになると 2 回実行されます。

ループを 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 に答える