SQLite的连接泄露虽然一切关闭 [英] SQLite Connection leaked although everything closed

查看:264
本文介绍了SQLite的连接泄露虽然一切关闭的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现很多东西,如关闭连接关闭游标,但我做这一切的东西。不过SQLite的连接泄漏,我得到这样的警告:

 为数据库中的SQLiteConnection对象被泄露!
 

我有一个数据库管理器这一点,我称之为我的活动有以下code:

 的DatabaseManager DBM =新的DatabaseManager(本);
 

我的数据库管理器类的code现在如下:

 公共类的DatabaseManager {

    私有静态最终诠释DATABASE_VERSION = 9;
    私有静态最后弦乐DATABASE_NAME =MyApp的;
    私人上下文的背景下= NULL;
    私人DatabaseHelper dbHelper = NULL;
    私人SQLiteDatabase DB = NULL;


    公共静态类DatabaseHelper扩展SQLiteOpenHelper {

         公共DatabaseHelper(上下文的背景下){
             超(背景下,DATABASE_NAME,空,DATABASE_VERSION);
         }

         @覆盖
         公共无效的onCreate(SQLiteDatabase DB){

                   //创建数据库表
         }

         @覆盖
         公共无效onUpgrade(SQLiteDatabase分贝,INT oldVersion,诠释静态网页){
                      //破坏并重新创建它们
         }

     }

     公众的DatabaseManager(上下文CTX){
         this.context = CTX;
     }

    私人的DatabaseManager的open()抛出的SQLException {
        dbHelper =新DatabaseHelper(上下文);
        DB = dbHelper.getWritableDatabase();

        如果(!db.isReadOnly()){
            db.execSQL(杂foreign_keys = ON;);
        }

        回到这一点;
    }

    私人无效的close(){
        dbHelper.close();
    }
}
 

当我调用数据库的方法,我做以下的事情:

 公开对象的getData(){

    打开();

            // ...数据库操作发生...

    关闭();

    返回的数据;
}
 

但正如我所说,我仍然得到这个SQLite的连接泄漏的警告。

我是什么做错了吗?

解决方案

在引文粗体字体对应于这部分在code:

 私人的DatabaseManager的open()抛出的SQLException {
    dbHelper =新DatabaseHelper(上下文);
    DB = dbHelper.getWritableDatabase();
 

从:<一href="http://www.androiddesignpatterns.com/2012/05/correctly-managing-your-sqlite-database.html">http://www.androiddesignpatterns.com/2012/05/correctly-managing-your-sqlite-database.html

  

方法1:使用抽象工厂来实例化   SQLiteOpenHelper

     

声明数据库助手作为一个静态实例变量和使用   Abstract Factory模式,以保证singleton属性。该   下面的示例code应该给你如何去个好主意   正确设计DatabaseHelper类。

     

静态工厂getInstance方法确保只有一个   DatabaseHelper将永远存在,在任何给定的时间。如果mInstance   对象尚未初始化,将创建一个。如果一个人   已经创建那么它将简单地返回。

  您应该   用的 新DatabaseHelper(上下文)使用未初始化辅助对象 的。
  相反,始终使用    DatabaseHelper.getInstance(上下文) 的,因为它保证只有一个   数据库助手将在整个应用程序的生命周期中存在。

 公共静态类DatabaseHelper扩展SQLiteOpenHelper {

  私有静态DatabaseHelper mInstance = NULL;

  私有静态最后弦乐DATABASE_NAME =数据库名称;
  私有静态最后弦乐DATABASE_TABLE =表格名;
  私有静态最终诠释DATABASE_VERSION = 1;

  公共静态DatabaseHelper的getInstance(上下文CTX){

    //使用应用程序上下文,这将确保你
    //不小心泄露了活动的背景。
    //请参阅本文的详细信息:http://bit.ly/6LRzfx
    如果(mInstance == NULL){
      mInstance =新DatabaseHelper(ctx.getApplicationContext());
    }
    返回mInstance;
  }

  / **
   *构造函数应该是私有的prevent直接实例。
   *化妆调用静态工厂方法的getInstance()代替。
   * /
  私人DatabaseHelper(上下文CTX){
    超(CTX,DATABASE_NAME,空,DATABASE_VERSION);
  }
}
 

I found many stuff like close the connection and close the cursor, but I do all this stuff. Still the SQLite connection leaks and I get a warning like this:

A SQLiteConnection object for database was leaked!

I have a database manager this, which I call in my activities with the following code:

DatabaseManager dbm = new DatabaseManager(this);

The code of my database manager class follows now:

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

When I call a database method, I do the following thing:

public Object getData() {

    open();

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

    close();

    return data;
}

But as I said, I still get this SQLite connection leaked warning.

What am I doing wrong?

解决方案

The bolded font in the citation corresponds to this part in your code:

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

Approach #1: Use an Abstract Factory to Instantiate the SQLiteOpenHelper

Declare your database helper as a static instance variable and use the Abstract Factory pattern to guarantee the singleton property. The sample code below should give you a good idea on how to go about designing the DatabaseHelper class correctly.

The static factory getInstance method ensures 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.

You should not initialize your helper object using with new DatabaseHelper(context).
Instead, always use DatabaseHelper.getInstance(context), as it guarantees that only one database helper will exist across the entire application's lifecycle.

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

这篇关于SQLite的连接泄露虽然一切关闭的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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