处理 SQLite 数据库的多个对象

Handle multiple objects for SQLite Database

我试图在 thread.But 中多次更新单个 SQLite 行项目,它抛出 close() was never explicitly called on database error.. 我做到了我的逻辑如下:

ta.addTextChangedListener(new TextWatcher() {

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {}

                @Override
                public void beforeTextChanged(CharSequence s, int start, int count,
                        int after) {}

                @Override
                public void afterTextChanged(final Editable s) {
                    // TODO Auto-generated method stub
                    Thread textThread = new Thread(new Runnable() {

                        @Override
                        public void run() {
                            mValues.open();
                            mValues.updateText(id, s.toString());                               
                            mValues.close();

                        }
                    });textThread.start();


                    Editor edittextEditor = checkPrefs.edit();
                    edittextEditor.putString(IncidentQuestionPage.EDITTEXT_KEY+id, s.toString());
                    edittextEditor.commit();
                }
            });

来自数据库的 updateText()、open() 和 close():

public IncidentValues open() throws SQLException {
    ourHelper = new DbHelper(context);
    ourDatabase = ourHelper.getWritableDatabase();
    return this;
}

public void close() {
    ourHelper.close();
}

public void updateText(String optionId, String text){
    ContentValues data=new ContentValues();
    data.put(VALUE, text);      
    ourDatabase.update(INCIDENT_VALUES_TABLE, data, INCIDENT_OPTION_ID+"=?", new String[] {optionId});
}

在 EditText 中更改数据后的Logcat:

    02-14 13:36:36.059: E/SQLiteDatabase(3679): close() was never explicitly called on database '/data/data/com.mondaz.globalfocusfocalpoint/databases/IncidentValues' 
    02-14 13:36:36.059: E/SQLiteDatabase(3679): android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here
    02-14 13:36:36.059: E/SQLiteDatabase(3679):     at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1944)
    02-14 13:36:36.059: E/SQLiteDatabase(3679):     at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1007)
    02-14 13:36:36.059: E/SQLiteDatabase(3679):     at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:986)
    02-14 13:36:36.059: E/SQLiteDatabase(3679):     at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1051)
    02-14 13:36:36.059: E/SQLiteDatabase(3679):     at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:800)
    02-14 13:36:36.059: E/SQLiteDatabase(3679):     at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:221)
    02-14 13:36:36.059: E/SQLiteDatabase(3679):     at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:157)
    02-14 13:36:36.059: E/SQLiteDatabase(3679):     at com.mondaz.globalfocusfocalpoint.localDb.IncidentValues.open(IncidentValues.java:62)
    02-14 13:36:36.059: E/SQLiteDatabase(3679):     at com.mondaz.globalfocusfocalpoint.adapter.IncidentQuestionAdapter.run(IncidentQuestionAdapter.java:221)
    02-14 13:36:36.059: E/SQLiteDatabase(3679):     at java.lang.Thread.run(Thread.java:856)
    02-14 13:36:36.060: E/System(3679): Uncaught exception thrown by finalizer
    02-14 13:36:36.061: E/System(3679): java.lang.IllegalStateException: Don't have database lock!
    02-14 13:36:36.061: E/System(3679):     at android.database.sqlite.SQLiteDatabase.verifyLockOwner(SQLiteDatabase.java:2091)
    02-14 13:36:36.061: E/System(3679):     at android.database.sqlite.SQLiteDatabase.entryRemoved(SQLiteDatabase.java:2183)
    02-14 13:36:36.061: E/System(3679):     at android.database.sqlite.SQLiteDatabase.entryRemoved(SQLiteDatabase.java:2179)
    02-14 13:36:36.061: E/System(3679):     at android.util.LruCache.trimToSize(LruCache.java:197)
    02-14 13:36:36.061: E/System(3679):     at android.util.LruCache.evictAll(LruCache.java:285)
    02-14 13:36:36.061: E/System(3679):     at android.database.sqlite.SQLiteDatabase.deallocCachedSqlStatements(SQLiteDatabase.java:2144)
    02-14 13:36:36.061: E/System(3679):     at android.database.sqlite.SQLiteDatabase.closeClosable(SQLiteDatabase.java:1126)
    02-14 13:36:36.061: E/System(3679):     at android.database.sqlite.SQLiteDatabase.finalize(SQLiteDatabase.java:1915)
    02-14 13:36:36.061: E/System(3679):     at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:182)
    02-14 13:36:36.061: E/System(3679):     at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:168)
    02-14 13:36:36.061: E/System(3679):     at java.lang.Thread.run(Thread.java:856)

我曾尝试将 Thread.sleep(1000) 放入线程中,但没有成功。

请建议如何处理这个多个数据库对象..

简单的解决方案:

不需要每次从线程 open/close 数据库。您应该必须在 onResume() 中打开数据库并在 onPause() 中关闭它以处理多个数据库实例。

简单更改您的代码来自:

@Override
  public void run() {
    mValues.open();
    mValues.updateText(id, s.toString());                               
    mValues.close();

}

@Override
 public void run() {
  mValues.updateText(id, s.toString());                               

}

然后按照我的建议打开和关闭数据库。 类似于:

//Open the Db when the Activity resumes
@Override
protected void onResume() {
    // TODO Auto-generated method stub
    super.onResume();
    dbInstance.open();
}

//Closethe it when the Activity pauses
@Override
protected void onPause() {
    // TODO Auto-generated method stub
    super.onPause();
    dbInstance.close(); 
}

编辑

我认为这个解决方案足以在适配器中处理它。或者您可以在适配器 class 中为打开和关闭创建两个用户定义的方法,并分别从 activity onResume() 和 onPause() 调用它们。类似于:

//for open
public void openDatabase(){
    dbInstance.open();
}
// //for close
public void closeDatabase(){
    dbInstance.close();
}

并从 activity.

调用它们
@Override
protected void onPause() {
    // TODO Auto-generated method stub
    super.onPause();
    mAdapter.closeDatabase();   
}

@Override
protected void onResume() {
    // TODO Auto-generated method stub
    super.onResume();
    mAdapter.openDatabase();
}

试试吧。应该可以。