代码之家  ›  专栏  ›  技术社区  ›  Alin

找到SQLite数据库泄漏

  •  2
  • Alin  · 技术社区  · 14 年前

    我正在创建应用程序。我得到这个错误:

    11-08 13:46:24.665:错误/数据库(443): java.lang.illegalState异常: /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 . 这是 异步任务 :

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

    如果我让活动顺其自然,一切都会好起来的。如果我不这样做,快速按下后退按钮,我就会得到错误。关于如何解决这个问题有什么建议吗?

    2 回复  |  直到 8 年前
        1
  •  4
  •   Reuben Scratton    14 年前

    我不确定你在用 SQLiteOpenHelper myDataBase 字段,其想法是为您管理数据库连接。不要这样子类化…除非你在 onCreate() 存取资料表 直接,即:

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

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

    如果后台任务是读取数据库的唯一内容,那么就让它拥有sqliteOpenHelper实例。静态数据很容易出错,所以最好避免IMHO。我会这样做:

    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
        }
    }
    
        2
  •  2
  •   Fraid    14 年前

    我认为这部分:

     cursor.close();
                    sqlite.closeDataBase();
                            sqlite.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
    }