Android SQLiteDB не заканчивает добавление значений

Моя SQLiteDatabase доставляет мне некоторые проблемы. Когда пользователь закрывает приложение, в onPause() AsyncTask начинает сохранять данные. Я не знаю, лучший ли это способ сделать это, но как я это сделал, сначала база данных удаляет все существующие данные (это не слишком много, может быть, 20-30 значений между двумя таблицами), затем добавляет свежие данные обратно в базу данных.

Метод deleteAll() работает просто отлично, но когда он пытается добавить каждый элемент, он терпит неудачу после 6-го.

Это мой метод doInBackground() для AsyncTask:

@Override
    protected Void doInBackground(Void... args) 
    {           
        //open database
        try 
        {
            myDbHelper.openDatabase();
        }catch(SQLException sqle)
        {    
            throw sqle;  
        }

        myDbHelper.deleteAll();

        //add all ingredients & units
        for (int i = 0; i < ingredients.size(); i++)
            myDbHelper.addIngredient(ingredients.get(i));
        for (int i = 0; i < units.size(); i++)
            myDbHelper.addUnit(units.get(i));

        myDbHelper.close();


        return null;
    }

Далее, вот методы deleteAll(), addIngredient() и addUnit() моего класса DatabaseHelper:

public void deleteAll() 
{
    int deletedIngredientCount = myDataBase.delete(TABLE_INGREDIENTS, "1", null);
    Log.d("QBCPro", deletedIngredientCount + " ingredients deleted successfully");

    int deletedUnitCount = myDataBase.delete(TABLE_UNITS, "1", null);
    Log.d("QBCPro", deletedUnitCount + " units deleted successfully");
}

public void addIngredient(Ingredient ingredient) 
{
    ContentValues values = new ContentValues();
    values.put(ING_KEY_NAME, ingredient.getName());
    values.put(ING_KEY_DENSITY, ingredient.getDensity());

    // Insert Row
    int row = (int) myDataBase.insert(TABLE_INGREDIENTS, null, values);
    if (row == -1)
        Log.d("QBCPro", "An error occurred, row == " + row);
    else
        Log.d("QBCPro", "Successfully inserted " + values.get(ING_KEY_NAME) + " into row " + row);
}

public void addUnit(Unit unit)
{
    ContentValues values = new ContentValues();
    values.put(UNIT_KEY_NAME, unit.getName());
    values.put(UNIT_KEY_BASE_VALUE, unit.getBaseValue());
    values.put(UNIT_KEY_FINAL_VALUE, unit.getFinalValue());
    values.put(UNIT_KEY_IS_WEIGHT, unit.getIsWeight());

    // Insert Row
    myDataBase.insert(TABLE_UNITS, null, values);
}

Наконец, вот журнал. Как видите, он резко завершается, вызывая только шесть раз addIngredient(). Также есть предупреждение showStatusIcon, но я не могу понять, откуда оно может исходить или что его вызывает.

02-13 18:47:32.320: D/QBCPro:::(25264): SaveAllTask: Saving to database...
02-13 18:47:32.405: W/IInputConnectionWrapper(25264): showStatusIcon on inactive InputConnection
02-13 18:47:32.445: D/QBCPro(25264): DatabaseHelper deleteAll() called.
02-13 18:47:32.480: D/QBCPro(25264): 11 ingredients deleted successfully
02-13 18:47:32.510: D/QBCPro(25264): 12 units deleted successfully
02-13 18:47:32.510: D/QBCPro(25264): Leaving DatabaseHelper deleteAll() method.
02-13 18:47:32.540: D/QBCPro(25264): Successfully inserted almonds (ground) into row 1
02-13 18:47:32.575: D/QBCPro(25264): Successfully inserted baking powder into row 2
02-13 18:47:32.610: D/QBCPro(25264): Successfully inserted baking soda into row 3
02-13 18:47:32.640: D/QBCPro(25264): Successfully inserted butter into row 4
02-13 18:47:32.685: D/QBCPro(25264): Successfully inserted cocoa powder into row 5
02-13 18:47:32.720: D/QBCPro(25264): Successfully inserted flour (all-purp) into row 6

Я предполагаю, что это вызывает утечку памяти или что-то в этом роде, потому что это конец журнала. Это также приводит к поломке приложения, потому что, когда я возвращаю его на передний план, я получаю кучу предупреждений IInputConnection, и все мои представления становятся невидимыми.

Любое понимание будет с благодарностью!

ОБНОВЛЕНИЕ:

Это перестало происходить без причины, но началось снова. Я не изменил никакого кода в базе данных (кроме операторов журнала), но я немного изменил основное действие, но это не должно иметь никакого отношения к базе данных. Вот что происходит:

Пользователь выходит из приложения, вызывается AsyncTask SaveAllTask. Код такой же, как и выше, но я добавил несколько операторов журнала, как вы можете видеть:

02-14 13:41:29.561: D/QBCPro:::(12104): SaveAllTask doInBackground called...
02-14 13:41:29.561: D/QBCPro:::(12104): SaveAllTask: ingredients.size() = 11
02-14 13:41:29.576: D/QBCPro:::(12104): SaveAllTask: units.size() = 12
02-14 13:41:29.616: D/QBCPro:::(12104): SaveAllTask: Saving to database...
02-14 13:41:29.671: W/IInputConnectionWrapper(12104): showStatusIcon on inactive InputConnection
02-14 13:41:29.701: D/QBCPro(12104): DatabaseHelper deleteAll() called.
02-14 13:41:29.736: D/QBCPro(12104): 11 ingredients deleted successfully
02-14 13:41:29.761: D/QBCPro(12104): 12 units deleted successfully
02-14 13:41:29.761: D/QBCPro(12104): Leaving DatabaseHelper deleteAll() method.
02-14 13:41:29.781: D/QBCPro(12104): Successfully inserted almonds (ground) into row 1
02-14 13:41:29.811: D/QBCPro(12104): Successfully inserted baking powder into row 2
02-14 13:41:29.836: D/QBCPro(12104): Successfully inserted baking soda into row 3
02-14 13:41:29.861: D/QBCPro(12104): Successfully inserted butter into row 4
02-14 13:41:29.886: D/QBCPro(12104): Successfully inserted cocoa powder into row 5
02-14 13:41:29.921: D/QBCPro(12104): Successfully inserted flour (all-purp) into row 6
02-14 13:41:29.961: D/QBCPro(12104): Successfully inserted flour (cake) into row 7
02-14 13:41:29.991: D/QBCPro(12104): Successfully inserted milk (2%) into row 8
02-14 13:41:30.021: D/QBCPro(12104): Successfully inserted sugar (br, packed) into row 9

Затем оно резко обрывается, как показано выше, хотя, как ни странно, в строке 9, а не в 6. Возвращение приложения на передний план вызывает AsyncTask LoadAllTask, что приводит к следующему:

02-14 13:43:57.106: D/QBCPro:::(12532): LoadAllTask doInBackground called...
02-14 13:43:57.121: D/QBCPro:::(12532): LoadAllTask: ingredients.size() == 9
02-14 13:43:57.121: D/QBCPro:::(12532): LoadAllTask: units.size() == 0
02-14 13:43:57.121: D/QBCPro(12532): Database CLOSED! (good thing)
02-14 13:43:57.121: D/QBCPro:::(12532): LoadAllTask doInBackground completed...

И у меня ломается приложение.

Я не думаю, что это необходимо, но на всякий случай вот мой код LoadAllTask:

@Override
    protected Void doInBackground(Void... params) 
    {
        Log.d(TAG, "LoadAllTask doInBackground called...");
        //open database
        try 
        {
            myDbHelper.openDatabase();
        }catch(SQLException sqle)
        {    
            throw sqle;  
        }

        //get all ingredients and units
        ingredients = myDbHelper.getAllIngredients();
        units = myDbHelper.getAllUnits();

        Log.d(TAG, "LoadAllTask: ingredients.size() == " + ingredients.size());
        Log.d(TAG, "LoadAllTask: units.size() == " + units.size());

        myDbHelper.close();
        Log.d(TAG, "LoadAllTask doInBackground completed...");
        return null;
    }

person S Fitz    schedule 13.02.2013    source источник
comment
Вы дважды проверили, сколько предметов находится в ingredients? Если была проблема, обычно есть исключение...   -  person Sam    schedule 13.02.2013
comment
Это странно... Я буквально не менял свой код, за исключением того, что добавил лог-оператор для ингредиентов.size() и unit.size(), и до сих пор он отлично работает каждый раз. Я собираюсь провести гораздо больше тестов, потому что я абсолютно не доверяю этому. Единственное другое отличие состоит в том, что со вчерашнего дня я перезагрузил и свой компьютер (и, следовательно, Eclipse), и свое тестовое устройство. Возможно виновато мое устройство и его перезагрузка помогла?   -  person S Fitz    schedule 14.02.2013
comment
Итак, это снова начало происходить необъяснимо. Я собираюсь обновить исходный пост немного больше информации.   -  person S Fitz    schedule 14.02.2013
comment
Есть ли исключение?   -  person Dan    schedule 14.02.2013
comment
Нет, единственное, что похоже на исключение, это IInputConnectionWrapper. Журнал просто останавливается на этом ингредиенте. Кроме того, onPostExecuted() никогда не вызывается, потому что я также добавляю туда операторы журнала. На самом деле, в конце doInBackground() я помещаю оператор, который также никогда не вызывается.   -  person S Fitz    schedule 14.02.2013
comment
Пользователь выходит из приложения, вызывается AsyncTask SaveAllTask. Я не эксперт по многопоточности, но я не знаю никаких гарантий, что AsyncTask завершится до того, как будет уничтожен. Попробуйте создать службу для запуска вашей AsyncTask, чтобы этот поток не был уничтожен, когда сборщик мусора очистит приложение.   -  person Sam    schedule 14.02.2013


Ответы (1)


Я исправил это, создав IntentService с AsyncTask внутри него и вызвав его в onPause. Теперь работает без ошибок. Вот код в onPause:

    Intent saveIntent = new Intent(this, SaveService.class);
    startService(saveIntent); 

А вот мой класс SaveService:

public class SaveService extends IntentService
{
    private ArrayList<Ingredient> ingredientsArray;
    private ArrayList<Unit> unitsArray;
    private DatabaseHelper dbHelper;

    public SaveService(String name) 
    {
        super(name);
    }

    public SaveService() 
    {
        super("SaveService");
    }

    @Override
    protected void onHandleIntent(Intent intent) 
    {
        //save data to database
        dbHelper = new DatabaseHelper(getApplicationContext());
        ingredientsArray = QuickBakeConverterPro.ingredients;
        unitsArray = QuickBakeConverterPro.units;

        new SaveAllTask().execute();
    }

    private class SaveAllTask extends AsyncTask<Void, Void, Void>
    {
        @Override
        protected Void doInBackground(Void... args) 
        {
            //open database
            try 
            {
                dbHelper.openDatabase();
            }catch(SQLException sqle)
            {    
                throw sqle;  
            }

            dbHelper.deleteAll();

            //add all ingredients & units
            for (int i = 0; i < ingredientsArray.size(); i++)
                dbHelper.addIngredient(ingredientsArray.get(i));
            for (int i = 0; i < unitsArray.size(); i++)
                dbHelper.addUnit(unitsArray.get(i));

            dbHelper.close();

            return null;
        }
    }//SaveAllTask
}//class SaveService
person S Fitz    schedule 05.03.2013