无法防止 SQLiteConnection 对象泄漏



在我的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;
}    

但是,既然你说我对你的问题的唯一贡献(已经在其他帖子中回答过(是改善你缺乏初级英语的问题,那么我不确定你是否可以接受这是一个足够的答案。

最新更新