I have a ListView with custom adapter which is populated from local sqlite database. When user long click the item and choose ‘delete’, dialog will popup to confirm the action again and item will be deleted after confirmed click.
My problem is that the item was deleted from database and the arraylist( dataset for adapter ) was updated, but the ListView isn’t updated eventhough I’ve already called the notifyDataSetChanged().
//The delete method is set on AlertDialog/PositiveButton click listener < ListView ContextMenu listener.
I’ve checked or tried the following things, but still…
1. Rebuild it (go onCreate), listview will show correctly then, so should be not other issue.
2. I called the same adapter, have confirmed by same hashCode
3. mListView.setAdapter((ListViewAdapter)(ListViewer.mListView.getAdapter()));
4. allResArray.clear(); loadData();
Can anyone help me please? Thanks. I’ve been stuck on it for 2 days!!
Here is my code:
private static ListView mListView;
private ListViewAdapter mListViewAdapter;
public String[] strListRID;
public List<List<String>> allResArray;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setView(R.layout.listviewer);
init();
}
public void init(){
setTitle(getString(R.string.app_name));
setTitleBar(R.drawable.title_home, 0, R.drawable.title_add, 0,
0, 0, R.drawable.titlebar_title, 0);
initListView();
}
//MainListView initialization
private void initListView(){
boolean SD_STATE = checkSDState();
allResArray = new ArrayList<List<String>>();
loadData();
mListView = (ListView) findViewById(R.id.ListView);
mListViewAdapter = new ListViewAdapter(this, SD_STATE, allResArray);
mListView.setAdapter(mListViewAdapter);
Log.i("mListViewAdapter", String.valueOf(mListViewAdapter.hashCode()));
mListView.setCacheColorHint(0x00000000);
// Click listener to ListView
mListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
goIntent(5, strListRID[position]);
}
});
// ContextMenu listener to ListView
mListView.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
@Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo) {
menu.setHeaderTitle(R.string.conext_menu_title);
menu.add(0, 0, 0, R.string.conext_menu_edit);
menu.add(0, 1, 0, R.string.conext_menu_delete);
}
});
}
@Override
public boolean onContextItemSelected(MenuItem item){
AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
switch (item.getItemId()) {
case 0: //Edit
goIntent(5, strListRID[menuInfo.position]);
return true;
case 1: //Delete
showDeleteDialog(strListRID[menuInfo.position], menuInfo.position);
break;
default:
break;
}
return super.onContextItemSelected(item);
}
private void loadData() {
allResArray = getAllDatabaseRes();
int size = allResArray.get(0).size();
strListRID = allResArray.get(0).toArray(new String[size]);
}
/**
* AlertDialog: confirm before delete data
* Remove it from ArrayList and notifyDataSetChanged() to adapter
* @param strListRID
*/
private void showDeleteDialog(final String strListRID, final int position) {
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
dialog.setIcon(R.drawable.dialog_notice);
dialog.setMessage(R.string.text_delete);
dialog.setPositiveButton(R.string.btn_delete, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (delRes(Integer.parseInt(strListRID))){
int size =((ListViewAdapter)(mListView.getAdapter())).mResArray.size();
for (int i = 0; i < size; i++){
((ListViewAdapter)(mListView.getAdapter())).mResArray.get(i).remove(position);
}
((ListViewAdapter)(ListViewer.mListView.getAdapter())).notifyDataSetChanged();
Log.i("mListViewAdapter_check", String.valueOf(((ListViewAdapter)(ListViewer.mListView.getAdapter())).hashCode()));
showShortToast((String) getResources().getText(R.string.text_record_delete_ok));
}
else{
showShortToast((String) getResources().getText(R.string.text_record_delete_ng));
}
}
});
dialog.setNegativeButton(R.string.text_no, null);
dialog.show();
}
delRes() code in BaseActivity:
/**
* Delete the specific rid record from database
* @return boolean DEL_OK
* @throws SQLException
*/
protected boolean delRes(int strRID) throws SQLException {
boolean DEL_OK = false;
String deleteWhere = "rid=?";
String[] deleteWhereValue = { String.valueOf(strRID)};
Log.i("rid to delete", deleteWhereValue[0]);
int delrow = dbHelper.delete(tables[0], deleteWhere, deleteWhereValue);
Log.i("delrow", String.valueOf(delrow));
if (delrow == 1){
DEL_OK = true;
}
return DEL_OK;
}
And the logCat:
02-09 15:19:59.744: I/mListViewAdapter(28235): 1163110296
02-09 15:19:59.784: I/tmp(28235): /sdcard/Photo/20120208164204.jpg
02-09 15:19:59.814: I/tmp(28235): /sdcard/Photo/20120208163627.jpg
02-09 15:19:59.854: I/tmp(28235): /sdcard/Photo/20120209151917.jpg
02-09 15:20:05.514: I/menuInfo.position(28235): 1
02-09 15:20:08.634: I/rid to delete(28235): 10
02-09 15:20:08.674: I/delrow(28235): 1
02-09 15:20:08.674: I/mListViewAdapter_check(28235): 1163110296
Current solution: Set a new listviewadapter
/**
* AlertDialog: confirm before delete data
* Remove it from ArrayList and notifyDataSetChanged() to adapter
* @param strListRID
*/
private void showDeleteDialog(final String mRID, final int position) {
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
dialog.setIcon(R.drawable.dialog_notice);
dialog.setMessage(R.string.text_delete);
dialog.setPositiveButton(R.string.btn_delete, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (delRes(Integer.parseInt(mRID))){
int size = allResArray.size();
for (int i = 0; i < size; i++){
allResArray.get(i).remove(position);
}
strListRID = allResArray.get(0).toArray(new String[size-1]);
//((ListViewAdapter)(mListView.getAdapter())).notifyDataSetChanged();
mListView.setAdapter(new ListViewAdapter(getApplicationContext(), true, allResArray));
showShortToast((String) getResources().getText(R.string.text_record_delete_ok));
}
else{
showShortToast((String) getResources().getText(R.string.text_record_delete_ng));
}
}
});
dialog.setNegativeButton(R.string.text_no, null);
dialog.show();
}
Try deleting the row specified directly from your adapter, and then calling notifyDataSetChanged(). Or you can just create new adapter, iterate your ArrayList and adding data to your new adapter, then set this adapter to your ListView.