gpt4 book ai didi

android SQLiteOpenHelper 和泄漏

转载 作者:行者123 更新时间:2023-11-29 15:32:04 30 4
gpt4 key购买 nike

我想用一些额外的方法(比如 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 是它们的逻辑占位符。

我在 Activity 中所做的是创建一个新的 DBHelper 实例并将其存储在 Activity 的私有(private)字段(称为 mDBHelper)中。另外,在 onDestroy Activity 方法中,我有 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();
}

这些 Activity 仅以一种方式使用 mDBHelper - 通过调用它的自定义方法,如 mDBHelper.getStreetsCursor()。最终我在 logcat 中发现了一条异常消息,关于我的应用程序在使用 DBHelper 的此类 Activity 中出现泄漏。它说类似“数据库从未关闭”之类的内容。所以我决定在返回之前在我的每个自定义方法中添加对 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();线。如果我删除它,everythig 工作正常,但我再次泄漏。所以我不知道出了什么问题。在每个自定义方法中,我都得到了 SQLiteDatabase dbReadable=this.getReadableDatabase();应该返回可读实例的行,但在执行 close() 方法后却没有。我猜这与我的自定义方法有关,因为它们在 DBHelper 实例中调用 .getReadableDatabase()。如果我将这些方法直接放在 Activity 中,一切正常——没有泄漏异常,并且每次方法都返回正确的数据。但我想将这些方法放在我的 DBHelper 类中。

所以主要问题是 - 出了什么问题以及如何正确处理?

最佳答案

你不应该有一个 SQLiteDatabase dbReadable=this.getReadableDatabase();
在每个方法 getSomethingCursor 中,因为请求数据库对象很昂贵(我想我是在 SO 中读到的)。

所以你可以从你的构造函数创建对象

  SQLiteDatabase dbReadable;

public DBHelper(Context context) {
super(context, DB_NAME, null, 1);
appContext=context;
dbReadable=this.getReadableDatabase()
}


public Cursor getStreetsCursor(String chars) {
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;
}

创建一个关闭数据库句柄的方法:

public closeDb() {
if (dbReadable != null) { dbReadable.close();}
}

在你的 Activity 中:

    @Override
protected void onDestroy() {
if (mDBHelper!=null){
mDBHelper.closeDb();
Log.i(APP_TAG,"mDBHelper.close() in "+this.getClass());
}
super.onDestroy();
}

并使用 startManagingCursor (如果 SDK < HoneyComb)让你的 Activity 管理你的光标(例如在 onDestroy 上关闭它

关于android SQLiteOpenHelper 和泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5441777/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com