Подтвердить что ты не робот

SQLite Connection просочилась, хотя все закрыто

Я нашел много вещей вроде close the connection и close the cursor, но я все это делаю. Однако соединение SQLite протекает, и я получаю предупреждение, подобное этому:

A SQLiteConnection object for database was leaked!

У меня есть менеджер баз данных, который я вызываю в своих действиях с помощью следующего кода:

DatabaseManager dbm = new DatabaseManager(this);

Ниже приведен код моего менеджера баз данных:

public class DatabaseManager {

    private static final int DATABASE_VERSION = 9;
    private static final String DATABASE_NAME = "MyApp";
    private Context context = null;
    private DatabaseHelper dbHelper = null;
    private SQLiteDatabase db = null;


    public static class DatabaseHelper extends SQLiteOpenHelper {

         public DatabaseHelper(Context context) {
             super(context, DATABASE_NAME, null, DATABASE_VERSION);
         }

         @Override
         public void onCreate(SQLiteDatabase db) {

                   //create database tables
         }

         @Override
         public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
                      //destroy and recreate them
         }

     }

     public DatabaseManager(Context ctx) {
         this.context = ctx;
     }

    private DatabaseManager open() throws SQLException {
        dbHelper = new DatabaseHelper(context);
        db = dbHelper.getWritableDatabase();

        if (!db.isReadOnly()) {
            db.execSQL("PRAGMA foreign_keys = ON;");
        }

        return this;
    }

    private void close() {
        dbHelper.close();
    }
}

Когда я вызываю метод базы данных, я делаю следующее:

public Object getData() {

    open();

            //... database operations take place ...

    close();

    return data;
}

Но, как я уже сказал, я все еще получаю это сообщение о утечке SQLite.

Что я делаю неправильно?

4b9b3361

Ответ 1

Жирный шрифт в цитате соответствует этой части вашего кода:

private DatabaseManager open() throws SQLException {
    dbHelper = new DatabaseHelper(context);
    db = dbHelper.getWritableDatabase();

from: http://www.androiddesignpatterns.com/2012/05/correctly-managing-your-sqlite-database.html

Подход № 1: используйте абстрактный Factory для создания SQLiteOpenHelper

Объявите свой помощник базы данных как статическую переменную экземпляра и используйте Абстрактный шаблон Factory, чтобы гарантировать свойство singleton. пример кода ниже должен дать вам хорошую идею о том, как идти правильно спроектировав класс DatabaseHelper.

Статический метод getInstance Factory гарантирует, что только один DatabaseHelper когда-либо будет существовать в любой момент времени. Если mInstance объект не был инициализирован, один будет создан. Если уже был создан, тогда он будет просто возвращен.

Вы должны не инициализируйте свой вспомогательный объект с помощью new DatabaseHelper(context).
Вместо этого всегда используйте DatabaseHelper.getInstance(context), поскольку это гарантирует, что только один помощник базы данных будет существовать во всем жизненном цикле приложения.

public static 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 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);
  }
}