【发布时间】:2011-07-23 10:37:51
【问题描述】:
我想用一些额外的方法(比如 getStreetsCursor)来制作 SQLiteOpenHelper,这些方法从我的数据库中返回数据。所以我写了这样的东西:
public class DBHelper extends SQLiteOpenHelper {
public static final String DB_NAME="some.db";
public static final String T1_NAME="streets";
public static final String T1_FNAME1="name";
public static final String T2_NAME="addresses";
public static final String T2_FNAME1="name";
public static final String T2_FNAME2="address";
private Context appContext;
public DBHelper(Context context) {
super(context, DB_NAME, null, 1);
appContext=context;
}
public Cursor getStreetsCursor(String chars) {
SQLiteDatabase dbReadable=this.getReadableDatabase();
Cursor curStreets = dbReadable.query(DBHelper.T1_NAME,
new String[] {"_id",DBHelper.T1_FNAME1},
DBHelper.T1_FNAME1+" LIKE(\""+chars.toUpperCase()+"%\")",
null, null, null, DBHelper.T1_FNAME1);
return curStreets;
}
在 DBHelper 中定义了几种方法,例如 getStreetsCursor(getAddresses、getAddress4 等)。 我想如果它是一个 DB Helper 它肯定应该有这样的方法,我的意思是 DBHelper 是它们的逻辑占位符。
我在活动中所做的是创建一个新的 DBHelper 实例并将其存储在活动的私有字段(称为 mDBHelper)中。此外,在 onDestroy 活动方法中,我有 mDBHelper.close()。
private DBHelper mDBHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mDBHelper = new DBHelper(this);
...
@Override
protected void onDestroy() {
if (mDBHelper!=null){
mDBHelper.close();
Log.i(APP_TAG,"mDBHelper.close() in "+this.getClass());
}
super.onDestroy();
}
这些活动仅以一种方式使用 mDBHelper - 通过调用它的自定义方法,例如 mDBHelper.getStreetsCursor()。 最终,我在 logcat 中发现了一条异常消息,提示我的应用在使用 DBHelper 的此类活动中发生泄漏。它说诸如“数据库从未关闭”之类的内容。所以我决定在返回之前在我的每个自定义方法中添加对 close() 方法的调用。所以它看起来像:
public Cursor getStreetsCursor(String chars) {
SQLiteDatabase dbReadable=this.getReadableDatabase();
Cursor curStreets = dbReadable.query(DBHelper.T1_NAME,
new String[] {"_id",DBHelper.T1_FNAME1},
DBHelper.T1_FNAME1+" LIKE(\""+chars.toUpperCase()+"%\")",
null, null, null, DBHelper.T1_FNAME1);
dbReadable.close();
return curStreets;
}
现在我没有泄漏,但遇到了下一个问题 - 只有第一次调用 mDBHelper.getStreetsCursor() 才真正执行。所有下一个调用都返回 null。那是由于 dbReadable.close();线。如果我删除它一切正常,但我再次泄漏。 所以我无法弄清楚出了什么问题。在每个自定义方法中,我都得到了 SQLiteDatabase dbReadable=this.getReadableDatabase();该行应该返回一个可读的实例,但在执行 close() 方法后它没有。 我猜它与我的自定义方法有关,因为它们在 DBHelper 的实例中调用 .getReadableDatabase()。如果我将这些方法直接放在活动中,一切正常 - 没有泄漏异常,并且每次方法返回正确的数据。但我想将这些方法放在我的 DBHelper 类中。
所以主要问题是 - 出了什么问题以及如何正确地做到这一点?
【问题讨论】:
标签: android sqlite memory-leaks