10

我有一个运行正常且不会强制关闭或崩溃的应用程序。但是当我查看 LogCat 时,它偶尔会给我这样的信息:

05-20 15:24:55.338: E/SQLiteDatabase(12707): close() was never explicitly called on database '/data/data/com.---.--/databases/debt.db' 
05-20 15:24:55.338: E/SQLiteDatabase(12707): android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here

有点下...

05-20 15:24:55.338: E/System(12707): Uncaught exception thrown by finalizer
05-20 15:24:55.338: E/System(12707): java.lang.IllegalStateException: Don't have database lock!

我不确定何时应该打开和关闭我的数据库?

我有一个主要活动,它只是一个闪屏。然后它进入一个使用数据库中的信息调用 ListView 的活动;因此,正是在活动中首次打开数据库。

还有一个其他活动需要数据库,它使用 ListVeew 将其分支出来。我应该什么时候打开和关闭这个?Word似乎是我只需要打开一次,然后在应用程序“暂停”、“停止”或“销毁”时关闭。

如果是这种情况,我应该将 db.close() 方法放在哪里……在 onStop 等所在的启动画面主活动中?还是与打开数据库的活动相同的活动?或者..还有别的地方吗?

更新:

这是错误一直指向的代码行:

public void open() throws SQLException {
    database = dbHelper.getWritableDatabase();
}
4

3 回答 3

9

如果您使用的是 DatabaseHelper 类的实例,并且在初始化 DBHelper 对象后,每次在数据库中工作时都应该在工作之前调用 open 方法,然后创建一个新游标,查询数据库,执行使用刚刚存储在游标中的信息,完成后关闭游标,然后关闭数据库。例如,如果您想获取数据库中的每个项目,您可以执行以下操作:

...    
DataBaseHelper db = new DataBaseHelper(this);
... 
db.open();
Cursor cursor = db.getAllItems(); 
maxCount = cursor.getCount(); 
Random gen = new Random();
row = gen.nextInt(maxCount); // Generate random between 0 and max
if (cursor.moveToPosition(row)) {
    String myString = cursor.getString(1);  //here I want the second column
    displayString(myString); //private method
}
cursor.close();
db.close(); 

getAllItems是我的公共方法,DatabaseHelper如果您想知道,它看起来像这样

public Cursor getAllItems() {
    return db.query(DATABASE_TABLE, 
        new String[] {
            KEY_ROWID, 
            KEY_NAME
        }, 
        null, 
        null, 
        null, 
        null, 
        null);
}

这就是我访问我的数据库的方式,并且我没有遇到您遇到的任何错误,并且它运行良好。

于 2012-05-20T23:25:29.183 回答
3

我曾经使用上面提到的@Shikima 的方式,但是在具有许多后台服务、多线程等的复杂应用程序中,当您必须管理许多数据库实例并且除此之外,打开和关闭它们时,它会变得非常烦人。

为了克服这个问题,我使用了以下方法,它似乎工作正常。

1.

Application基类中声明并初始化YourDBHelperClass的一个实例,如下所示:

public class App extends Application {
  public static YourDBHelperClass db;

  @Override
  public void onCreate() {
    super.onCreate();
    db = new YourDBHelperClass(getApplicationContext());
    db.open();

  }
}

2.

在您的活动中,或您想使用数据库的任何其他地方,初始化 YourDBHelperClass 对象,如下所示:

YourDBHelperClass db = App.db;

然后您可以随心所欲地使用数据库,而不必担心每次都手动打开和关闭它。SQLiteOpenHelper在应用程序被销毁时负责关闭

于 2014-03-11T05:58:48.243 回答
2

您可能没有正确处理您的数据库;您打开的数据库实例多于关闭的数据库实例。

您可以遵循许多设计模式来纠正此行为。您可能需要查阅此答案以获取更多信息。

于 2012-05-20T23:24:19.987 回答