问题
My SQLiteDatabase is giving me some trouble. When the user closes the app, in onPause() an AsyncTask begins to save the data. I don't know if this is the best way to do it, but the way I have done it is, first the database deletes all of the existing data (it's not too much, maybe 20-30 values between two tables), then adds the fresh data back into the database.
The deleteAll() method works just fine, but when it tries to add each item, it fails after the 6th one.
This is my doInBackground() method of the 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;
}
Next, here are the deleteAll(), addIngredient() and addUnit() methods of my DatabaseHelper class:
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);
}
Finally, here's the log. As you can see, it finishes abruptly, only calling addIngredient() six times. There's also the showStatusIcon warning, but I can't figure out where that might be coming from, or what's causing it.
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
I'm guessing this causes a memory leak or something, because this is the end of the log. It also causes the app to break because when I bring it back to the foreground I get a bunch of IInputConnection warnings and all of my views are invisible.
Any insight would be greatly appreciated!
UPDATE:
It stopped happening for no reason, but it's starting again. I haven't changed any code in the database (other than log statements), but I have changed a bit in the main Activity, but it shouldn't have any bearing on the database. Here's what happens:
User exits app, AsyncTask SaveAllTask is called. The code is the same as above, but I added some log statements, as you can see:
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
Then it abruptly ends, like above, though strangely at row 9 rather than 6. Bringing the app back into the foreground calls AsyncTask LoadAllTask, leading to this:
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...
And my app breaks.
I don't think it's necessary, but just in case, here's my LoadAllTask code:
@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;
}
回答1:
I fixed this by creating an IntentService with an AsyncTask inside of it, and calling it within onPause. It works error-free now. Here's the code in onPause:
Intent saveIntent = new Intent(this, SaveService.class);
startService(saveIntent);
And here's my SaveService class:
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
来源:https://stackoverflow.com/questions/14859063/android-sqlitedb-doesnt-finish-adding-values