【问题标题】:SQLite connection object leaked - AndroidSQLite 连接对象泄露 - Android
【发布时间】:2014-02-25 02:25:35
【问题描述】:

我正在制作我的第一个 android 应用程序,我首先学习了一些 sqlite 教程,这些教程教我使用扩展 SQLiteOpenHelper 的 databaseHelper。所以我的 databaseHelper 确实扩展了 SQLiteOpenHelper。我在 Logcat 中收到了一个 sqlite 连接泄漏警告,所以想要一些关于如何解决这个问题的建议。

我得到这个错误:

02-01 21:39:50.740: W/SQLiteConnectionPool(32061): A SQLiteConnection object for database '/data/data/com.btf271.fashionassistant/databases/clothingManager' was leaked!  Please fix your application to end transactions in progress properly and to close the database when it is no longer needed.

在发生泄漏时调用的我的 databaseHelper 函数:

 public List<Sticker> getObjectsByGenderAndCategory(String gender, String category) {
        List<Sticker> objects = new ArrayList<Object>();
        String selectQuery = String.format(
                "SELECT * FROM %s WHERE %s = \"%s\" AND %s = \"%s\"",
                TABLE_OBJECT, KEY_GENDER, gender, KEY_CATEGORY, category);

        Log.e(LOG, selectQuery);

        SQLiteDatabase db = this.getReadableDatabase();
        Cursor c = db.rawQuery(selectQuery, null);
     try{
        // looping through all rows and adding to list
        if (c.moveToFirst()) {
            do {
                Object o = createClothingItemJavaObject(c);

                // adding to object list
                objects.add(o);
            } while (c.moveToNext());
        }
     }finally {
           c.close();
db.close();
     }
        return objects;
    }

我找到了this which I will try tomorrow. It's late

谢谢。

【问题讨论】:

标签: java android sqlite memory-leaks sqliteopenhelper


【解决方案1】:

我所做的只是implement this answer to a similar question,现在它没有显示 SQL 连接对象泄漏错误。我不能推荐这个。实施和工作只需要几分钟。

代码如下:

public class DatabaseHelper extends SQLiteOpenHelper { 

  private static DatabaseHelper mInstance = null;

  private static final String DATABASE_NAME = "database_name";
  private static final String DATABASE_TABLE = "table_name";
  private static final int DATABASE_VERSION = 1;

  public static DatabaseHelper getInstance(Context ctx) {

    // Use the application context, which will ensure that you 
    // don't accidentally leak an Activity's context.
    // See this article for more information: http://bit.ly/6LRzfx
    if (mInstance == null) {
      mInstance = new DatabaseHelper(ctx.getApplicationContext());
    }
    return mInstance;
  }

  /**
   * Constructor should be private to prevent direct instantiation.
   * make call to static factory method "getInstance()" instead.
   */
  private DatabaseHelper(Context ctx) {
    super(ctx, DATABASE_NAME, null, DATABASE_VERSION);
  }
}

【讨论】:

  • 我在使用它后仍然得到这个问题,但只有在编辑一些强度条件时,它仍然处于痛苦状态(idk)..
  • 你能帮忙解决这个问题吗issue
【解决方案2】:

我通过添加解决了这个问题

@Override
protected void finalize() throws Throwable {
    this.close();
    super.finalize();
}

到我的 SQLiteOpenHelper 扩展类

【讨论】:

  • 谢谢。这个对我有用。它解决了我的数据库无法从我所做的许多查询中接近的全球问题。你能解释一下这段代码的实际作用吗?
  • 这通过隐藏泄漏使错误消失。这不是一个很好的解决方案,因为数据库连接只会在垃圾收集后关闭 - 可能比您应该关闭它要晚得多。
  • @DavidSainty 我知道这以一种不雅的方式解决了泄漏问题,而不是掩盖了问题。你有什么建议?
  • @tonygil finalize 仅在数据库连接完全未使用且未正确 close()-d 后运行一段时间。完成后最好显式地关闭()数据库连接,这就是这个警告试图鼓励你做的事情。
【解决方案3】:

将每个对getReadableDatabase()getWritableDatabase() 的调用与同一数据库对象上对应的close() 匹配。

例如,您的getAllClothingItemsByGenderAndCategory() 调用getReadableDatabase() 但不close() 它。在c.close() 之后添加db.close()

您的closeDB() 没有任何意义,因为它使用getReadableDatabase() 获得了对数据库的新引用并仅关闭那个。它不会关闭任何现有的数据库连接。

【讨论】:

  • 谢谢。刚刚做到了。好的会忘记我的closeDB()。我的问题中的最后一个代码块怎么样,我是否也应该尝试添加一个 mDb.close()?
  • 没有足够的上下文来判断关闭助手的合适位置。
  • 好的,所以我想这告诉我,我不应该每次在完成后实例化它就关闭它。干杯。任何情况我应该关闭它?一些上下文是:该代码块位于 onCreate() 中,用于设置有关哪个用户正在使用该应用程序的一些信息。
  • 请您帮忙解决这个问题issue
【解决方案4】:

每次打开数据库(可读或可写)时,使用内存资源的游标必须使用“.close();”释放在每个数据库函数中使用结束后.. by your_database object.close();和光标 object.close();

【讨论】:

  • @user6224849...请更改您所说的内容。它以某种方式获得了赞成票,但不清楚,因为您的措辞和语法不太好。
猜你喜欢
  • 2015-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-18
  • 1970-01-01
  • 1970-01-01
  • 2011-06-11
  • 1970-01-01
相关资源
最近更新 更多