我目前正在为Android上的ListView编写自定义BaseAdapter。当我第一次在ListView中插入项目时,列表适配器基本上工作正常,但是在中间插入新项目后,调用后会显示错误的项目
notifyDataSetChanged();
这是一个简化的例子(我把它剥离到只有必要的,如果我错过了任何信息,请说明评论):
public class FriendListAdapter extends BaseAdapter {
private ArrayList<SingleFriend> data;
private Activity activity = null;
private static int needAccept = -1;
private static int friend = -2;
private static int waiting = -3;
public FriendListAdapter(Activity a) {
this.activity = a;
data = new ArrayList<>();
}
public void AddFriend(SingleFriend newFriend, boolean silent) {
int insertInto = 0;
switch (newFriend.getFriendType()) {
case TYPE_FRIEND_WAIT_FOR_YOUR_ACCEPT:
insertInto = needAccept;
break;
case TYPE_FRIEND_WAIT_FOR_HIS_ACCEPT:
insertInto = waiting;
break;
case TYPE_FRIEND_ACCEPTED:
insertInto = friend;
break;
}
if (insertInto < 0) {
boolean found = false;
boolean inserted = false;
int index = 0;
do {
if (data.get(index).getFriendID() == insertInto) {
found = true;
} else if (found) {
if (data.get(index).getFriendID() < 0) {
data.add(index, newFriend);
inserted = true;
} else {
if (newFriend.getFriendName().compareToIgnoreCase(data.get(index).getFriendName()) < 0) {
data.add(index, newFriend);
inserted = true;
}
}
}
if (!inserted && index == data.size() - 1) {
data.add(newFriend);
inserted = true;
}
++index;
} while (index < data.size() && !inserted);
}
if (!silent) {
notifyDataSetChanged();
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
if (vi == null) {
LayoutInflater inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
SingleFriend friend = (SingleFriend)getItem(position);
if (friend != null) {
switch (friend.getFriendType()) {
case TYPE_SEPARATOR:
vi = inflater.inflate(R.layout.friendlist_topic, null);
vi.setTag(friend);
((TextView)vi.findViewById(R.id.friendTopic)).setText(friend.getFriendName());
break;
case TYPE_FRIEND_ACCEPTED:
case TYPE_FRIEND_WAIT_FOR_HIS_ACCEPT:
case TYPE_FRIEND_WAIT_FOR_YOUR_ACCEPT:
// TODO: Community rating!
vi = inflater.inflate(R.layout.friendlist_item, null);
vi.setTag(friend);
((TextView)vi.findViewById(R.id.friendName)).setText(friend.getFriendName());
break;
default:
break;
}
}
}
return vi;
}
}
在FriendList中插入好友后,为什么显示错误的数据?我错过了什么吗?即使invalidate()也没有显示正确的东西(我知道,invalidate是一个糟糕的选择,我只是为测试目的而做了一次)。提前谢谢!
答案 0 :(得分:1)
有太多问题,但我认为你要解决的问题是由这种情况检查造成的(或主要是由此引起的):
if (vi == null) {...
convertView
方法中的 getView
并非始终为null,而是在您满足上述检查时为该行的视图充气。我认为在您向上和向下滚动后,内容将不再正确关联项目。
我注意到的其他问题是,
每次修改适配器所耦合的列表时,都应该调用 notifyDataSetChanged
。如果你想隐藏一些元素,那么你应该保留两个列表。适配器的一个纯粹用于显示。
我认为您希望根据ID的可用性将项目插入到列表中。如果是这种情况,那么比循环寻找ID的列表更好的方法是使用像HashMap<id, SingleFriend>
这样的地图,get(id)
可以随机访问。
您应该首先了解getView的工作原理并正确使用View Holder pattern。