问题
In my Android app I have a DB where store Phrase objects, and Theme objects, among other data. These phrases have an attribute sourceLanguage (String) and an isSelected attribute (String too, since SQLITE doesn't have boolean - can't recall why I didn't use 0 and 1, but that's not relevant). The themes contain one or more phrases.
I have one activity where the user is given a listView with a list of themes. When he picks a theme, an alert dialog displays with a checkbox list of phrases so he can select one or more. I'd like to update each phrase in the DB using the information from the AlertDialog checkboxes, changing isSelected to "true" or to "false", depending on the user's choice.
My difficulty is that the examples I found online so far allow to save the "true" state of the elements, but not the "false". So if a phrase is stored as "true", and then changed to "false", it will simply not appear in the selectedItems, and I don't have a reference to access it and modify it to "false". I've come up with a couple of solutions, but I'm not confident about any, and this is where you could help me.
My AlertDialog method:
private void showAlertDialog(int themeId, String themeName) {
// TODO Auto-generated method stub
// Build the list of phrases for respective theme and list of previously selected items
final DatabaseHandler db = new DatabaseHandler(this);
List<Phrase> allThemePhr = db.getPhrases("with_theme", themeId, null); // all phrases for selected theme
CharSequence[] sourceLanguageAllPhr = new String[allThemePhr.size()]; // source language of all phrases for selected theme
boolean[] selectedItems = new boolean[allThemePhr.size()]; // selected items only
final List<String> sourceLanguageSelectedPhr = new ArrayList<String>();
final List<String> sourceLanguageNOTSelectedPhr = new ArrayList<String>();
for (int i = 0 ; i < allThemePhr.size() ; i++){
sourceLanguageAllPhr[i] = allThemePhr.get(i).getSource_language();
selectedItems[i] = false;
if (allThemePhr.get(i).getItemSelected() == "true"){
selectedItems[i] = true;
sourceLanguageSelectedPhr.add(allThemePhr.get(i).getSource_language());
}
}
// Build the dialog
@SuppressWarnings("rawtypes")
final ArrayList selectedPhrases = new ArrayList();
AlertDialog.Builder builder = new AlertDialog.Builder(PickTheme.this);
builder.setTitle(themeName)
.setMultiChoiceItems(sourceLanguageAllPhr, selectedItems, new DialogInterface.OnMultiChoiceClickListener() {
@SuppressWarnings("unchecked")
@Override
public void onClick(DialogInterface dialog, int which,
boolean isChecked) {
// TODO Auto-generated method stub
if(isChecked){
selectedPhrases.add(which);
//sourceLanguageSelectedPhr.add(selectedPhrases.get(which).toString());
} else if (selectedPhrases.contains(which)){
selectedPhrases.remove(Integer.valueOf(which));
//sourceLanguageSelectedPhr.remove(selectedPhrases.get(which).toString());
//sourceLanguageNOTSelectedPhr.add(selectedPhrases.get(which).toString());
}
}
})
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
//for (String sourceLanguage : sourceLanguageSelectedPhr){
//db.updatePhrase(sourceLanguage, "true");
//Log.i("selectedPhrase", selectedPhrases.get(which).toString());
//}
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
});
builder.create().show();
}
In my DatabaseHelper class, I've defined these methods that can be used to update phrases:
// updating a phrase
public int updatePhrase(Phrase phrase){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(COLUMN_PHRASE_ID, phrase.getWord_id());
values.put(COLUMN_SOURCE_LANGUAGE, phrase.getSource_language());
values.put(COLUMN_TARGET_LANGUAGE, phrase.getTarget_language());
values.put(COLUMN_PHRASE_REMINDER_DATE, phrase.getTarget_language());
values.put(COLUMN_PHRASE_THEME_ID, phrase.getTheme_id());
values.put(COLUMN_PHRASE_REMINDER_ID, phrase.getTheme_id());
int phraseUpdated = db.update(PHRASES_TABLE, values, COLUMN_PHRASE_ID + " =?", new String[] {String.valueOf(phrase.getWord_id())});
db.close();
return phraseUpdated;
}
// updating a phrase based on given source_language
public void updatePhrase(String sourceLanguage, String isSelected){
SQLiteDatabase db = this.getWritableDatabase();
String updateStatement = "UPDATE " + PHRASES_TABLE
+ " SET " + COLUMN_ITEM_SELECTED + " = " + isSelected
+ " WHERE " + COLUMN_SOURCE_LANGUAGE + " = " + sourceLanguage;
db.execSQL(updateStatement);
}
So far, I've thought of a few solutions, this one seemed the best: when a phrase is selected / de-selected, get it from the allThemePhr, update the object accordingly, and save it in another List. If user clicks OK, use that list to update the DB. My problem is: how to I match the value of which with the respective object in allThemePhr ? If I can figure out how to get the checkbox text, that should be acceptable, since it corresponds to the source_language attribute of phrase?
Maybe there is a simpler solution?
Thanks
回答1:
There is a match between the index which and the index the phrase objects have in the global phrases List allThemePhr, so no need to go through the string of the checkbox / the value of sourceLanguage.
So, I simply created a map where I store the correspondence between the index which and the status of the checkbox (isChecked). Then, if the user presses "OK", I iterate through that map, get the corresponding phrase object from allThemePhr and update it.
Here is the final code:
private void showAlertDialog(int themeId, String themeName) {
// TODO Auto-generated method stub
// Build the list of phrases for respective theme and list of previously selected items
final DatabaseHandler db = new DatabaseHandler(this);
final List<Phrase> allThemePhr = db.getPhrases("with_theme", themeId, null); // all phrases for selected theme
final Map<Integer, Boolean> selectionChanges = new HashMap<Integer,Boolean>();
CharSequence[] sourceLanguageAllPhr = new String[allThemePhr.size()]; // source language of all phrases for selected theme
boolean[] selectedItems = new boolean[allThemePhr.size()]; // selected items only
for (int i = 0 ; i < allThemePhr.size() ; i++){
Phrase phrase = allThemePhr.get(i);
sourceLanguageAllPhr[i] = phrase.getSource_language();
if (phrase.getItemSelected().equals("true")){
selectedItems[i] = true;
}
}
// Build the dialog
AlertDialog.Builder builder = new AlertDialog.Builder(PickTheme.this);
builder.setTitle(themeName)
.setMultiChoiceItems(sourceLanguageAllPhr, selectedItems, new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int which,
boolean isChecked) {
selectionChanges.put(which, isChecked);
}
})
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
for (Map.Entry<Integer, Boolean> entry : selectionChanges.entrySet()){
Phrase phrase = allThemePhr.get(entry.getKey());
phrase.setItemSelected(String.valueOf(entry.getValue()));
}
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
});
builder.create().show();
}
来源:https://stackoverflow.com/questions/23144447/how-to-save-state-of-checkboxes-in-database-both-true-and-false-states