Java Android sqlite日志报告和db.close()
日志报告数据库或游标未关闭。我基本上有一个带有自定义surfaceview的活动,并使用处理程序向该活动报告。当我收到消息时,我会显示一个alertdialog并更新数据库Java Android sqlite日志报告和db.close(),java,android,sqlite,Java,Android,Sqlite,日志报告数据库或游标未关闭。我基本上有一个带有自定义surfaceview的活动,并使用处理程序向该活动报告。当我收到消息时,我会显示一个alertdialog并更新数据库 private Handler handler = new Handler() { public void handleMessage(Message msg) { switch(msg.what) { case 1: dh.open();
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch(msg.what) {
case 1:
dh.open();
dh.updateEvent("id", "name", "someone");
dh.close();
successAlert.show();
break;
case 2:
failAlert.show();
break;
}
}
};
以前我没有“dh.close()”,这就是日志报告的数据库/游标未关闭的时候。但自从我在中添加这一点以来,它需要很长时间才能完成。一旦我得到这个信息,系统就好像挂了。是我做错了什么,还是通常要花这么长时间。我还尝试使用带有finally的try块来关闭db
编辑:
}
扩展的SQLiteOpenHelper:
public class Database extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "events.db";
private static final int DATABASE_VERSION = 1;
private static final String TABLE_NAME = "stateTable";
private static final String ID = "id";
private static final String NAME = "name";
private static final String OTHER = "other";
private static final String DATABASE_CREATE = "CREATE TABLE stateTable (id INT, name TEXT, other INT)";
private static final String DATABASE_UPGRADE = "DROP TABLE IF EXISTS table";
public Database(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
// TODO Auto-generated constructor stub
}
@Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
db.execSQL(DATABASE_CREATE);
// added initial values
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
db.execSQL(DATABASE_UPGRADE);
onCreate(db);
}
}
我认为这里您应该关闭数据库句柄db
,而不是dbHelper
同样在您的checkState
方法中:
public boolean checkState(int id) {
db = dbHelper.getReadableDatabase();
Cursor cursor = db.query("stateTable", null, null, null, null, null, null);
cursor.moveToPosition(id - 1);
int i = cursor.getInt(2);
android.util.Log.d("semajhan", ": " + i);
if (i == 1) {
return true;
} else {
return false;
}
}
您可能希望关闭光标,如下所示:
int i = cursor.getInt(2);
cursor.close();
android.util.Log.d("semajhan", ": " + i);
我想知道光标未关闭的根本问题是否与中的相同:活动需要有一个关闭DatabaseHelper的
onDestroy
方法。(我现在所能说的是,你没有显示ondestory
方法,但这显然只是你代码的一部分。)我也写了关于这个问题的博客
您还写道:“但是自从我添加[dh.close()
]以来,它需要很长时间才能完成。”您是否对数据库进行了大量写入?也许您需要使用事务定期刷新这些写入。如果您只是从数据库中读取,那么我不知道为什么close
调用需要很长时间才能完成。但是没有看到更多的代码,这些只是猜测
EDIT:'s关于在调用dbHelper()之前调用db.close()
的建议值得遵循。但是,您需要检查db是否为null。这将检查状态更改为:
public boolean checkState(int id) {
if (db != null) {
db.close();
}
db = dbHelper.getReadableDatabase();
// ... etc ....
如果这是真正的问题,请接受切尼森的答案,而不是我的
(上面的编辑不正确;我应该知道得更清楚!请参见下文。)
编辑1:我不确定您为什么要用这种方法打开数据库。假设调用了DatabaseHelper.open
方法,则具有可读的和可写的数据库句柄<代码>检查状态
不需要重新打开它来执行读取
编辑2:但是,几乎总是返回从SQLiteOpenHelper.getWriteableDatabase
返回的相同数据库句柄。不需要显式关闭该数据库句柄;SQLiteOpenHelper将为您关闭它。您确实需要确保在活动被销毁时调用SQLiteOpenHelper.close
。第一次调用SQLiteOpenHelper
实例的getReadableDatabase
或getwriteabledatabase
需要很长时间才能完成。每次需要查询数据库时,不应创建新的数据库
对象(您的SQLiteOpenHelper
实例)。尝试在DatabaseHelper
中使用相同的数据库
实例
使用SQLiteOpenHelper
时,您不希望关闭SQLiteDatabase
对象的SQLiteOpenHelper
,因为它是共享的;i、 e.getWritableDatabase
始终返回相同的SQLiteDatabase
对象
请注意,您的checkState
方法泄漏了一个光标。为了防止光标泄漏,我总是在获得光标后使用try
-finally
。例如:
db = dbHelper.getReadableDatabase();
Cursor cursor = db.query("stateTable", null, null, null, null, null, null);
try {
cursor.moveToPosition(id - 1);
int i = cursor.getInt(2);
android.util.Log.d("semajhan", ": " + i);
if (i == 1) {
return true;
} else {
return false;
}
} finally {
cursor.close();
}
处理程序代码看起来不错,但是我们看不到您的dh
是如何编码的,所以很难说是什么导致了延迟。我们将在一秒钟内发布更多代码。好的,数据库编码在哪里?除非它是adk的一部分,我在任何地方都看不到它…数据库是SQLiteOpenHelper扩展类。问题是,我已经做了所有这些。在我以前的代码中,我使用db close的句柄而不是dbHelper。在我的checkState方法中,我还调用了cursor.close()。但这导致了泄漏。一旦我从关闭db切换到dbHelper,泄漏就消失了,但我的日志中出现了一些奇怪的错误。只要一堆数字,给我一个百分比:user=72%kernel=28%之类的
,首先尝试关闭数据库:db.close();db=dbHelper.getReadableDatabase()代码>。在此之后,没有其他想法:)首先关闭db会导致强制关闭=[查看DDMS下的LogCat,看看是否有任何堆栈跟踪可以帮助我们调试找到的DDMS,但在LogCat中,我没有看到任何与“堆栈跟踪”相关的内容。我现在正在查看你的博客和链接。我只写了一行3列:一个INT、TEXT和另一个INT。这对SQL来说是非常新的,但我只写1行3列应该非常快。所以基本上,当我创建SQLiteOpenHelper的实例时,我已经“打开”了用于读写的数据库?对于读,我不需要显式调用db.getReadableDatabase()?@semajhan:不完全是。在你调用db.getWriteableDatabase
或db.getReadableDatabase
之前,数据库是不会打开的。但是调用db.getWriteableDatabase
可以让你读取和写入数据库。因此我认为你在调用之后不需要调用db.getReadableDatabase
ode>db.getWriteableDatabase
。啊,这很有道理。因此,如果我已经调用了getWriteableDatabase(),我就不需要调用getReadableDatabase()。但假设我在getWriteableDatabase()之后调用getReadableDatabase(),这是否意味着我正在打开数据库两次,可能会导致泄漏?@semajhan:不,它不会导致泄漏。SQLiteOpenHelper
保留对数据库h的引用
int i = cursor.getInt(2);
cursor.close();
android.util.Log.d("semajhan", ": " + i);
public boolean checkState(int id) {
if (db != null) {
db.close();
}
db = dbHelper.getReadableDatabase();
// ... etc ....
db = dbHelper.getReadableDatabase();
Cursor cursor = db.query("stateTable", null, null, null, null, null, null);
try {
cursor.moveToPosition(id - 1);
int i = cursor.getInt(2);
android.util.Log.d("semajhan", ": " + i);
if (i == 1) {
return true;
} else {
return false;
}
} finally {
cursor.close();
}