0

この SQLite エラーに出くわすまで、私のアプリケーションは正常に動作していました。

java.lang.IllegalMoniterStateException: attempt to unlock read lock, not locked by current thread

StackOverflow で他のすべての回答を試しましたが、役に立たなかったようです。彼らは皆、SQLiteDBAdpdter のインスタンスを作成する複数のスレッドがあると言っていましたが、私は Activity しか持っていませんが、それは SherlockFragmentActivity です。各クラスは SQliteDBAdapter の新しいインスタンスを作成するため、これがこのエラーの原因かどうかはわかりません。

私はこれに何時間も立ち往生しており、助けていただければ幸いです。

フラグメント 1:

public final class NotesFragment extends SherlockListFragment {
NotesDbAdapter db;
private static final int ACTIVITY_EDIT = 1;

private static final int DELETE_ID = Menu.FIRST + 1;

public static NotesFragment newInstance(String content) {
    NotesFragment fragment = new NotesFragment();

    return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    db = new NotesDbAdapter(getActivity());

    db.open();
    if (db.fetchAllNotes().getCount() == 0) {
        doWelcomeMessage();
    }
    db.close();

}

private void doWelcomeMessage() {
    // Show welcome dialog
    startActivity(new Intent(getActivity(), NotesWelcome.class));

}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    if (container == null) {
        return null;
    }

    db = new NotesDbAdapter(getActivity());

    db.open();
    if (db.fetchAllNotes().getCount() == 0) {
        doWelcomeMessage();
    }
    db.close();


    return ll;

}

}

エラーはメソッドで指してdb.open();います。メソッドは次onCreate()のとおりです。open()SQLiteDBAdapter (NotesDBAdapter)

public NotesDbAdapter open() throws SQLException {
    mDbHelper = new DatabaseHelper(mCtx);
    mDb = mDbHelper.getWritableDatabase();
    return this;
}

そして、onCreate()私の NotesDBAdapter は次のとおりです。

@Override
    public void onCreate(SQLiteDatabase db) {

        SQLiteDatabase checkDB = null;

        String myPath = "data/data/com.xxx.xxx/databases/data.db";
        checkDB = SQLiteDatabase.openDatabase(myPath, null,
                SQLiteDatabase.OPEN_READONLY);
        if (checkDB != null) {
            // exists; do nothing
        } else {
            // create DB

            db.execSQL(DATABASE_CREATE);

        } 

    }

再度、感謝します!

編集 他のフラグメント

新しいインスタンスの作成

データベースのフラグメント 2 はフラグメント 2 と呼ばれますが、実際にはフラグメント 1 と同じであるため、そのコードは示しませんでした。

4

2 に答える 2

1

これが問題かどうかはわかりませんが、書き込みのために同じデータベースを 2 回開いているようです。1 つだけ開いて、アプリケーション内で共有してください。

こちらもお読みください: Android のスレッド化とデータベースのロック

于 2013-04-15T15:16:27.043 に答える
1

あなたが書く:

各クラスは SQliteDBAdapter の新しいインスタンスを作成するため、これがこのエラーの原因かどうかはわかりません。

あなたの例には 2 つの部分クラスしか表示されないため、どのクラスを意味するのかわかりませNotesFragmentNotesDbAdapter。ただし、アクティビティがデータベースを開閉する他のクラスに依存している場合は、DB を開こうとする再帰的な試行がないことを確認する必要があります。(つまり、クラス A はデータベースを開き、次にクラス B を呼び出します。クラス B は、DBHelper の独自のインスタンスを使用してデータベースを開こうとします。その時点で、A がデータベースを開いている間に、B がデータベースを開こうとしています。)

dongshengcnが以前に指摘したように、それはバグである可能性があります。NotesFragment.onCreateでデータベースを開き、 でデータベースを閉じて、からこれらの他のクラスにオブジェクトNotesFragment.onDestroyを渡す方が適切な場合があります。dbNotesFragment

次の質問は、NotesDbAdapterクラスに適切なcloseメソッドがあるかどうかです。これは次のように表示され、(前述のように) から呼び出される必要がありNotesFragment.onDestroyます。

    @Override
    public synchronized void close() {

        if (mDbHelper != null) {
            mDbHelper.close();
            mDbHelper = null;
        }

        super.close();
    }
于 2013-04-15T17:00:00.630 に答える