Android SQLite尝试解锁读锁定,而不是被当前线程锁定

时间:2013-04-15 14:56:01

标签: java android database sqlite java.lang.class

我的应用程序运行正常,直到我偶然发现了这个SQLite错误:

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

我已经在StackOverflow上尝试了所有其他答案,但它们似乎没有帮助。他们都说我有多个线程创建我的SQLiteDBAdpdter的实例,但我只有Activity,但它只有SherlockFragmentActivity。每个类都创建一个SQliteDBAdapter的新实例,所以我不确定这是否是我收到此错误的原因。

我被困在这几个小时,并且 GREATLY 感谢任何帮助。

片段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;
}

我的NotesDBAdapter中的onCreate()是:

@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,但我没有将其代码显示为真正与片段1相同。

2 个答案:

答案 0 :(得分:1)

我不确定这是不是问题,但似乎你要为写入打开两次相同的数据库。请打开一个并在您的应用程序中共享它。

请在此处阅读:Android threading and database locking

答案 1 :(得分:1)

你写道:

  

每个类都创建一个SQliteDBAdapter的新实例,所以   我不确定这是否是我收到此错误的原因。

我不确定你在哪个课程,因为我在你的例子中只看到两个部分课程 - NotesFragmentNotesDbAdapter。但是,如果您的活动依赖于每个打开和关闭数据库的其他类,那么您必须确保没有任何递归尝试打开数据库。 (即,A类打开数据库,然后调用B类,它尝试使用自己的DBHelper实例打开数据库。此时,B正在尝试打开数据库,而A打开它。)

正如前面提到的dongshengcn,这可能是错误。在NotesFragment.onCreate中打开数据库并在NotesFragment.onDestroy中关闭它,并将db对象从NotesFragment传递到其他类中可能更合适。

接下来的问题是,您的NotesDbAdapter班级是否有适当的close方法?它应该看起来像这样,并且(如上所述)从NotesFragment.onDestroy调用。

    @Override
    public synchronized void close() {

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

        super.close();
    }