发现 SQLite 数据库泄漏

发布于 2024-10-01 07:37:48 字数 2310 浏览 8 评论 0 原文

我正在创建一个应用程序。我收到此错误:

11-08 13:46:24.665: 错误/数据库 (443): java.lang.IllegalStateException: /data/data/com.testproj/databases/Testdb SQLiteDatabase 创建并 从未关闭

我似乎找不到原因,因为它有时会向我显示错误,有时不会。这是我的代码:

public class SQLiteAssistant extends SQLiteOpenHelper {
    public SQLiteAssistant(Context context){
            super(context, DB_NAME, null, DB_VERSION_NUMBER);
            this.myContext = context;
    }

    public void openDataBase() throws SQLException{
        String myPath = DB_PATH + DB_NAME;
        myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
    }

    public void closeDataBase() {
        if(this.myDataBase != null) {
            if(this.myDataBase.isOpen())
                this.myDataBase.close();
            }
        }   
    }
}

在另一个类中,我有这些查询:

public class Db{  

    private static SQLiteAssistant sqlite;

    public static String getSomeString(Context ctx) {

        sqlite = new SQLiteAssistant(ctx);
        sqlite.openDataBase();

        Cursor cursor = sqlite.myDataBase.rawQuery("SELECT someColumn from SomeTable",null);

        if (cursor != null) {
            if (cursor.getCount()==1) {
                 if(cursor.moveToFirst()) {
                     String testString = cursor.getString(cursor.getColumnIndex("someColumn")); 
                     cursor.close();
                     sqlite.closeDataBase();
                     sqlite.close();
                     return testString
                 }
            }
        }

        sqlite.closeDataBase();
        sqlite.close();

        return null;
     }
}

我的问题是当我启动一个新活动时,我在其中得到一个 AsyncTask。此任务从 Web 服务获取数据并访问数据库以获取 String。这是AsyncTask

protected class BackTask extends AsyncTask<Context, String, String> {
     @Override
     protected String doInBackground(Context... params) {
         try{
            //get requeste data from the database
            //access the web service

            return result;

         } catch (Exception e) { 
                   return null;
         }
         return null;
     }
}

如果我让活动顺其自然,一切都会顺利。如果我不这样做并快速按后退按钮,则会收到错误消息。关于如何解决这个问题有什么建议吗?

I'm creating an application. I'm getting this error:

11-08 13:46:24.665: ERROR/Database(443):
java.lang.IllegalStateException:
/data/data/com.testproj/databases/Testdb SQLiteDatabase created and
never closed

I can't seem to find the reason for this, as it somethimes shows me the error, sometimes not. Here is my code:

public class SQLiteAssistant extends SQLiteOpenHelper {
    public SQLiteAssistant(Context context){
            super(context, DB_NAME, null, DB_VERSION_NUMBER);
            this.myContext = context;
    }

    public void openDataBase() throws SQLException{
        String myPath = DB_PATH + DB_NAME;
        myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
    }

    public void closeDataBase() {
        if(this.myDataBase != null) {
            if(this.myDataBase.isOpen())
                this.myDataBase.close();
            }
        }   
    }
}

In another class, I have these queries:

public class Db{  

    private static SQLiteAssistant sqlite;

    public static String getSomeString(Context ctx) {

        sqlite = new SQLiteAssistant(ctx);
        sqlite.openDataBase();

        Cursor cursor = sqlite.myDataBase.rawQuery("SELECT someColumn from SomeTable",null);

        if (cursor != null) {
            if (cursor.getCount()==1) {
                 if(cursor.moveToFirst()) {
                     String testString = cursor.getString(cursor.getColumnIndex("someColumn")); 
                     cursor.close();
                     sqlite.closeDataBase();
                     sqlite.close();
                     return testString
                 }
            }
        }

        sqlite.closeDataBase();
        sqlite.close();

        return null;
     }
}

My problem is when I start a new activity in which I get an AsyncTask. This task gets data from a web service and accesses the database for the String. Here is the AsyncTask:

protected class BackTask extends AsyncTask<Context, String, String> {
     @Override
     protected String doInBackground(Context... params) {
         try{
            //get requeste data from the database
            //access the web service

            return result;

         } catch (Exception e) { 
                   return null;
         }
         return null;
     }
}

If I let the activity take its course, everything goes fine. If I don't and quickly press the back button, I get the error. Any suggestion on how to solve this problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

知足的幸福 2024-10-08 07:37:48

我不确定您是否正确使用 SQLiteOpenHelper...您不需要该 myDataBase 字段,其想法是它为您管理数据库连接。不要以这种方式子类化...除非您在 onCreate() 等中执行未在此处发布的操作,看起来您可以直接使用 SQLiteOpenHelper ,即:

SQLiteOpenHelper sqlite = new SQLiteOpenHelper(ctx, DB_PATH+DB_NAME, null,
    DB_VERSION_NUMBER);

假设结束活动也应该停止您的后台任务,我建议致电 AsyncTask.cancel(true) 来自您的 Activity.onPause()。确保通过 onCancelled() 清除数据库。

如果您的后台任务是唯一读取数据库的任务,那么让它拥有 SQLiteOpenHelper 实例。静态数据很容易陷入麻烦,所以恕我直言,最好避免它。我会做这样的事情:

protected class BackTask extends AsyncTask<String, Integer, String>
{
    private SQLiteOpenHelper sqlite;

    public void BackTask(Context ctx) {
        sqlite = new SQLiteOpenHelper(ctx, DB_PATH+DB_NAME, null,
                                      DB_VERSION_NUMBER);
    }
    @Override
    protected String doInBackground(String... params) 
    {
         try {
                //get requeste data from the database
                //access the web service
                return result;

              } catch (Exception e) { 
         }
         return null;
    }

    @Override
    protected void onCancelled() {
         sqlite.close();
    }

    @Override
    protected void onPostExecute(String result)
         sqlite.close();
         // Update UI here
    }
}

Am not sure you're using SQLiteOpenHelper properly... you don't need that myDataBase field, the idea is that it manages your database connection for you. Don't subclass in that way... unless you're doing things in onCreate() etc that aren't posted here it looks like you can just use SQLiteOpenHelper directly, i.e.:

SQLiteOpenHelper sqlite = new SQLiteOpenHelper(ctx, DB_PATH+DB_NAME, null,
    DB_VERSION_NUMBER);

Assuming that ending the activity should also stop your background task, I'd recommend calling AsyncTask.cancel(true) from your Activity.onPause(). Ensure the database is cleaned up from onCancelled().

And if your background task is the only thing reading the database then make it own the SQLiteOpenHelper instance. It's easy to get into trouble with static data, so it's best avoided IMHO. I'd do something like this:

protected class BackTask extends AsyncTask<String, Integer, String>
{
    private SQLiteOpenHelper sqlite;

    public void BackTask(Context ctx) {
        sqlite = new SQLiteOpenHelper(ctx, DB_PATH+DB_NAME, null,
                                      DB_VERSION_NUMBER);
    }
    @Override
    protected String doInBackground(String... params) 
    {
         try {
                //get requeste data from the database
                //access the web service
                return result;

              } catch (Exception e) { 
         }
         return null;
    }

    @Override
    protected void onCancelled() {
         sqlite.close();
    }

    @Override
    protected void onPostExecute(String result)
         sqlite.close();
         // Update UI here
    }
}
盛夏尉蓝 2024-10-08 07:37:48

我认为这部分:

 cursor.close();
                sqlite.closeDataBase();
                        sqlite.close();

必须在finally close中,比如

Try{ 
    //Do something
   }
   catch(){
     //Catch exception
   }
   finally{
   //Close cursor or/and eventually close database if you don't need it in the future
   }

也不要忘记在onDestroy方法中关闭数据库。

onCreate(Bundle b){ 
//create database instance
}
onDestroy{
//close db
}

I think this part :

 cursor.close();
                sqlite.closeDataBase();
                        sqlite.close();

must be in a finally close like

Try{ 
    //Do something
   }
   catch(){
     //Catch exception
   }
   finally{
   //Close cursor or/and eventually close database if you don't need it in the future
   }

Also don't forget to close database in onDestroy method .

onCreate(Bundle b){ 
//create database instance
}
onDestroy{
//close db
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文