无法防止 SQLiteConnection 对象泄漏
Unable to prevent SQLiteConnection object leakage
在我的 Android 应用程序中,我有一些使用 SQLite 的数据库事务,但尽管尝试了很多方法来防止泄漏,但我还是遇到了 SQLiteConnection 对象泄漏。我几乎尝试了互联网上的每一件事,比如关闭数据库、关闭游标或结束事务。以下是 android studio 中的警告。
A SQLiteConnection object for database '/data/user/0/com.example.myapp/databases/myapp.dbnotes.db' was leaked! Please fix your application to end transactions in progress properly and to close the database when it is no longer needed.
有时通过关闭数据库或关闭游标我曾经得到错误 -
Attempt to reopen an already-closed object ....
。我不是 Android 的专家,我正在尝试自己学习,所以你能帮助我吗?我已经发布了以下代码:
DBHelper 内部 class
public class DBHelper extends SQLiteOpenHelper {
...
public static DBHelper getInstance(Context ctx) {
if (mInstance == null) {
mInstance = new DBHelper(ctx.getApplicationContext());
}
return mInstance;
}
private DBHelper(Context context) {
super(context, DB_NAME, null, 1);
this.context = context;
DB_PATH = context.getDatabasePath(DB_NAME).getPath();
}
...
private Cursor getData(String Query) {
String myPath = DB_PATH + DB_NAME;
Cursor c = null;
try {
db = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
c = db.rawQuery(Query, null);
} catch (Exception e) {
e.printStackTrace();
}
return c;
}
private void dml(String Query) {
String myPath = DB_PATH + DB_NAME;
if (db == null)
db = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
try {
db.execSQL(Query);
} catch (Exception e) {
e.printStackTrace();
}
}
//Methods to perform different db transaction
public void addToSubject(ItemSubject itemSubject) {
if (checkSuggested(itemSubject.getId())) {
dml("delete from " + TABLE_SUBJECT + " where id = '" + itemSubject.getId() + "'");
}
String insert = "insert into TABLE_SUBJECT .....";
dml(insert);
}
public void cleartable_subject() {
String delete = "delete from " + TABLE_SUBJECT;
dml(delete);
}
public long subject_size() {
if (db == null) {
db = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READWRITE);
}
try {
long count = DatabaseUtils.queryNumEntries(db, TABLE_SUBJECT);
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
private Boolean checkSubject(String id) {
String select = "select * from " + TABLE_SUBJECT + " where id = '" + id + "'";
Cursor cursor = getData(select);
return cursor != null && cursor.getCount() > 0;
}
public ArrayList<ItemSubject> loadDataSubject() {
ArrayList<ItemSubject> arrayList = new ArrayList<>();
String select = "select * from " + TABLE_SUBJECT;
Cursor cursor = getData(select);
if (cursor != null && cursor.getCount() > 0) {
cursor.moveToFirst();
for (int i = 0; i < cursor.getCount(); i++) {
String id = cursor.getString(cursor.getColumnIndex(TAG_ID));
String course = cursor.getString(cursor.getColumnIndex(TAG_COURSE_NAME));
....
ItemSubject objItem = new ItemSubject(id, courseId,...);
arrayList.add(objItem);
cursor.moveToNext();
}
cursor.close();
}
return arrayList;
}
//There are more similar methods for other tables
我正在像
这样的片段和活动中访问这些方法
dbHelper = DBHelper.getInstance(getActivity());
if ((dbHelper.subject_size() >= 1){
dbHelper.cleartable_subject();
for (int i = 0; i < arrayListSubject.size(); i++) {
dbHelper.addToSubject(arrayListSubject.get(i));
}
arrayListSubject = dbHelper.loadDataSubject();
}
抱歉,代码太长了,但我认为一切都是必要的。你能帮帮我吗?
你说你在网上查了很多问题,但你肯定没查this or this。它确实在搜索 5 分钟后突然出现。
无论如何,如果我是你,要解决这个问题,我会在关闭连接时包含一个 finally
子句。这意味着您会将数据库助手声明为静态实例变量,并使用抽象工厂模式来保证单例 属性.
您发出警告是因为您无法确保在任何给定时间只会存在一个 DatabaseHelper
。如果 mInstance
对象还没有被初始化,一个将被创建。如果已经创建了一个,那么它将被简单地返回。
代码如下:
public ArrayList<ItemSubject> loadDataSubject() {
ArrayList<ItemSubject> arrayList = new ArrayList<>();
String select = "select * from " + TABLE_SUBJECT;
Cursor cursor = getData(select);
if (cursor != null && cursor.getCount() > 0) {
try {
cursor.moveToFirst();
for (int i = 0; i < cursor.getCount(); i++) {
String id = cursor.getString(cursor.getColumnIndex(TAG_ID));
String course = cursor.getString(cursor.getColumnIndex(TAG_COURSE_NAME));
....
ItemSubject objItem = new ItemSubject(id, courseId,...);
arrayList.add(objItem);
cursor.moveToNext();
}
finally {
if (cursor != null)
cursor.close();
}
}
return arrayList;
}
但是既然你说我对你的问题(已经在其他帖子中回答过)的唯一贡献是改进你缺乏的基础英语,那么我不确定你是否可以接受这个作为一个足够的回答。
在我的 Android 应用程序中,我有一些使用 SQLite 的数据库事务,但尽管尝试了很多方法来防止泄漏,但我还是遇到了 SQLiteConnection 对象泄漏。我几乎尝试了互联网上的每一件事,比如关闭数据库、关闭游标或结束事务。以下是 android studio 中的警告。
A SQLiteConnection object for database '/data/user/0/com.example.myapp/databases/myapp.dbnotes.db' was leaked! Please fix your application to end transactions in progress properly and to close the database when it is no longer needed.
有时通过关闭数据库或关闭游标我曾经得到错误 -
Attempt to reopen an already-closed object ....
。我不是 Android 的专家,我正在尝试自己学习,所以你能帮助我吗?我已经发布了以下代码:
DBHelper 内部 class
public class DBHelper extends SQLiteOpenHelper { ... public static DBHelper getInstance(Context ctx) { if (mInstance == null) { mInstance = new DBHelper(ctx.getApplicationContext()); } return mInstance; } private DBHelper(Context context) { super(context, DB_NAME, null, 1); this.context = context; DB_PATH = context.getDatabasePath(DB_NAME).getPath(); } ... private Cursor getData(String Query) { String myPath = DB_PATH + DB_NAME; Cursor c = null; try { db = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE); c = db.rawQuery(Query, null); } catch (Exception e) { e.printStackTrace(); } return c; } private void dml(String Query) { String myPath = DB_PATH + DB_NAME; if (db == null) db = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE); try { db.execSQL(Query); } catch (Exception e) { e.printStackTrace(); } } //Methods to perform different db transaction public void addToSubject(ItemSubject itemSubject) { if (checkSuggested(itemSubject.getId())) { dml("delete from " + TABLE_SUBJECT + " where id = '" + itemSubject.getId() + "'"); } String insert = "insert into TABLE_SUBJECT ....."; dml(insert); } public void cleartable_subject() { String delete = "delete from " + TABLE_SUBJECT; dml(delete); } public long subject_size() { if (db == null) { db = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READWRITE); } try { long count = DatabaseUtils.queryNumEntries(db, TABLE_SUBJECT); return count; } catch (Exception e) { e.printStackTrace(); return 0; } } private Boolean checkSubject(String id) { String select = "select * from " + TABLE_SUBJECT + " where id = '" + id + "'"; Cursor cursor = getData(select); return cursor != null && cursor.getCount() > 0; } public ArrayList<ItemSubject> loadDataSubject() { ArrayList<ItemSubject> arrayList = new ArrayList<>(); String select = "select * from " + TABLE_SUBJECT; Cursor cursor = getData(select); if (cursor != null && cursor.getCount() > 0) { cursor.moveToFirst(); for (int i = 0; i < cursor.getCount(); i++) { String id = cursor.getString(cursor.getColumnIndex(TAG_ID)); String course = cursor.getString(cursor.getColumnIndex(TAG_COURSE_NAME)); .... ItemSubject objItem = new ItemSubject(id, courseId,...); arrayList.add(objItem); cursor.moveToNext(); } cursor.close(); } return arrayList; } //There are more similar methods for other tables
我正在像
这样的片段和活动中访问这些方法 dbHelper = DBHelper.getInstance(getActivity());
if ((dbHelper.subject_size() >= 1){
dbHelper.cleartable_subject();
for (int i = 0; i < arrayListSubject.size(); i++) {
dbHelper.addToSubject(arrayListSubject.get(i));
}
arrayListSubject = dbHelper.loadDataSubject();
}
抱歉,代码太长了,但我认为一切都是必要的。你能帮帮我吗?
你说你在网上查了很多问题,但你肯定没查this or this。它确实在搜索 5 分钟后突然出现。
无论如何,如果我是你,要解决这个问题,我会在关闭连接时包含一个 finally
子句。这意味着您会将数据库助手声明为静态实例变量,并使用抽象工厂模式来保证单例 属性.
您发出警告是因为您无法确保在任何给定时间只会存在一个 DatabaseHelper
。如果 mInstance
对象还没有被初始化,一个将被创建。如果已经创建了一个,那么它将被简单地返回。
代码如下:
public ArrayList<ItemSubject> loadDataSubject() {
ArrayList<ItemSubject> arrayList = new ArrayList<>();
String select = "select * from " + TABLE_SUBJECT;
Cursor cursor = getData(select);
if (cursor != null && cursor.getCount() > 0) {
try {
cursor.moveToFirst();
for (int i = 0; i < cursor.getCount(); i++) {
String id = cursor.getString(cursor.getColumnIndex(TAG_ID));
String course = cursor.getString(cursor.getColumnIndex(TAG_COURSE_NAME));
....
ItemSubject objItem = new ItemSubject(id, courseId,...);
arrayList.add(objItem);
cursor.moveToNext();
}
finally {
if (cursor != null)
cursor.close();
}
}
return arrayList;
}
但是既然你说我对你的问题(已经在其他帖子中回答过)的唯一贡献是改进你缺乏的基础英语,那么我不确定你是否可以接受这个作为一个足够的回答。