在我的Android应用程序中,我有一些使用SQLite的数据库事务,但是尽管尝试了许多方法来防止泄漏,但我还是遇到了SQLiteConnection对象泄漏。我几乎尝试了互联网上的每一件事,比如关闭数据库、关闭光标或结束交易。以下是安卓工作室中的警告。
数据库'/data/user/0/com.example.myapp/databases/myapp.dbnotes.db'的SQLiteConnection对象被泄露了! 请修复您的应用程序,以正确结束正在进行的事务,并在不再需要数据库时关闭数据库。
有时通过关闭数据库或关闭光标,我曾经得到错误 -Attempt to reopen an already-closed object ....
.我不是安卓专业,我正在尝试自己学习,所以你能帮我吗?我已经发布了以下代码:
-
在DBHelper类内部
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();
}
很抱歉代码很长,但我认为一切都是必要的。你能帮帮我吗?
你说你在网上调查了很多问题,但你绝对没有研究这个或这个。它实际上在搜索 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;
}
但是,既然你说我对你的问题的唯一贡献(已经在其他帖子中回答过(是改善你缺乏初级英语的问题,那么我不确定你是否可以接受这是一个足够的答案。