【发布时间】:2012-03-01 16:35:00
【问题描述】:
我有一个带有自定义适配器的 ListView,它是从本地 sqlite 数据库填充的。当用户长按项目并选择“删除”时,将弹出对话框再次确认操作,并在确认单击后删除项目。
我的问题是该项目已从数据库中删除,并且 arraylist(adapter 的数据集)已更新,但 ListView 未更新,即使我已经调用了 notifyDataSetChanged()。
//删除方法设置在AlertDialog/PositiveButton click listener
我已经检查或尝试了以下事情,但仍然...
1。重建它(继续创建),然后列表视图将正确显示,所以应该不是其他问题。
2。我调用了相同的适配器,已通过相同的 hashCode 确认
3。 mListView.setAdapter((ListViewAdapter)(ListViewer.mListView.getAdapter()));
4。 allResArray.clear();加载数据();
谁能帮帮我?谢谢。我已经卡了2天了!!
这是我的代码:
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();
}
BaseActivity中的delRes()代码:
/**
* 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;
}
还有 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
当前解决方案:设置新的 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();
}
【问题讨论】:
-
你能解释一下你在这个声明中做了什么吗? for (int i = 0; i
-
List
- > allResArray;其中包括 8 个 List
。这是从每个列表中删除选定的项目。 -
抱歉 4 问了太多问题,但请告诉我一些事情..1) 您的列表视图实际上向用户显示了什么?列出对象? 2)您的 Arraylist 绑定到您的适配器(我同意),但不是从该 ArrayList 中删除项目,而是从该 ArrayList 内的列表中删除单个项目。您认为这将如何影响您的列表视图对最终用户的外观?
-
感谢您的提问,但我有点困惑。 listview 将 allResArray 作为参数传递给 listviewadapter 以构建一个包含多个 textview 和 imageview 的视图。这是我定制的listviewadapter。调用adapter.notifyDataSetChanged()不是目的吗?它可以像 setAdapter() 一样调用 getView() 来刷新列表视图,我有什么误解吗?谢谢。顺便说一句,我也试过 setAdapter(),没有运气......
-
目前的解决方案是新建一个适配器。我不认为重新初始化一个是正确的,UI总是重新加载并显示在顶部位置,我猜用户体验很糟糕......