无法防止 SQLiteConnection 对象泄漏 [英] Unable to prevent SQLiteConnection object leakage

查看:25
本文介绍了无法防止 SQLiteConnection 对象泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的 Android 应用程序中,我有一些使用 SQLite 的数据库事务,但尽管尝试了多种方法来防止泄漏,但我还是遇到了 SQLiteConnection 对象泄漏.我几乎尝试过互联网上的每件事,比如关闭数据库、关闭游标或结束事务.以下是android studio中的警告.

In my Android app, I have some Database transaction using SQLite but I am getting SQLiteConnection object leakage despite trying many ways to prevent the leak. I have almost tried each and every thing in the internet like closing the db, closing the cursor, or ending the transaction. Below is the warning in android studio.

数据库'/data/user/0/com.example.myapp/databases/myapp.dbnotes.db'的SQLiteConnection对象被泄露!请修复您的应用程序以正确结束正在进行的事务并在不再需要时关闭数据库.

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.

有时通过关闭数据库或关闭游标我曾经得到错误 -尝试重新打开一个已经关闭的对象.....我不是 Android 专业人士,我正在尝试自己学习,所以你能帮我.我已经发布了以下代码:

Sometimes by closing the db or closing the cursor I used to get error - Attempt to reopen an already-closed object ..... I am not pro in Android, I am trying to learn by my own self , so could you help me. I have posted the codes below:

  • DBHelper 类内部

  • Inside the 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

我正在片段和活动中访问这些方法

I am accessing these methods inside fragments and activities like

     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();
     }

对不起,代码很长,但我认为一切都是必要的.你能帮我吗?

Sorry for the long section of codes, but I thought everything will be necessary. Could you please help me?

推荐答案

你说你在网上查了很多问题,但你绝对没有查 this这个.它确实在 5 分钟内出现在搜索中.

You say you looked into many questions online, but you definitely didn't look into this or this. It literally cropped up 5 minutes into searching.

无论如何,如果我是你,要解决这个问题,我会在关闭连接时包含一个 finally 子句.这意味着您需要将数据库助手声明为静态实例变量,并使用抽象工厂模式来保证单例属性.

Anyways, if I were you, to resolve this issue, I would include a finally clause when closing the connection. This means that you would be declaring your database helper as a static instance variable and use the Abstract Factory pattern to guarantee the singleton property.

之所以发生您的警告,是因为您不能确保在任何给定时间都只存在一个 DatabaseHelper.如果 mInstance 对象尚未初始化,则会创建一个.如果一个已经被创建,那么它会被简单地返回.

Your warning is happening because you are not ensuring that only one DatabaseHelper will ever exist at any given time. If the mInstance object has not been initialized, one will be created. If one has already been created then it will simply be returned.

代码如下:

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;
}    

但既然你说我对你的问题的唯一贡献(已经在其他帖子中回答过)是改善你缺乏基本英语的能力,那么我不确定你是否能接受这个作为一个充分的答案.

But since you say that my only contribution to your question (which had already been answered in other posts) is that of refining your lack of elementary English, then I am not that sure if you can accept this as an adequate answer.

这篇关于无法防止 SQLiteConnection 对象泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆