Обнаружена утечка базы данных SQLite - PullRequest
2 голосов
/ 08 ноября 2010

Я создаю приложение.Я получаю эту ошибку:

11-08 13: 46: 24.665: ОШИБКА / База данных (443): java.lang.IllegalStateException: /data/data/com.testproj/databases/TestdbБаза данных SQLite создана и никогда не закрывается

Кажется, я не могу найти причину этого, так как иногда она показывает ошибку, иногда нет.Вот мой код:

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.Эта задача получает данные из веб-службы и обращается к базе данных для 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;
     }
}

Если я позволю занятию идти своим чередом, все будет хорошо.Если я этого не сделаю и быстро нажму кнопку «Назад», я получу ошибку.Любое предложение о том, как решить эту проблему?

Ответы [ 2 ]

4 голосов
/ 08 ноября 2010

Не уверен, что вы используете 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
    }
}
2 голосов
/ 08 ноября 2010

Я думаю, что эта часть:

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