我的ListView
正在使用BaseAdapter
的扩展程序,我无法正确刷新它。当我刷新时,似乎旧数据在新数据之上绘制,直到滚动事件发生。旧行绘制在新行的顶部,但是当我开始滚动时,旧行会消失。
我尝试过调用invalidateViews()
,notifyDataSetChanged()
和notifyDataSetInvalidated()
。我的代码看起来像:
private void updateData()
{
List<DataItems> newList = getNewList();
MyAdapter adapter = new MyAdapter(getContext());
//my adapter holds an internal list of DataItems
adapter.setList(newList);
mList.setAdapter(adapter);
adapter.notifyDataSetChanged();
mList.invalidateViews();
}
答案 0 :(得分:59)
对于仍有问题的人,我这样解决了:
List<Item> newItems = databaseHandler.getItems();
ListArrayAdapter.clear();
ListArrayAdapter.addAll(newItems);
ListArrayAdapter.notifyDataSetChanged();
databaseHandler.close();
我首先清除了适配器中的数据,然后添加了新的项集合,然后才设置notifyDataSetChanged();
起初我不清楚这一点,所以我想指出这一点。请注意,如果不调用notifyDataSetChanged()
,视图将不会更新。
答案 1 :(得分:12)
据我了解,如果您想在数据发生变化时立即刷新ListView,则应在notifyDataSetChanged()
中致电RunOnUiThread()
。
private void updateData() {
List<Data> newData = getYourNewData();
mAdapter.setList(yourNewList);
runOnUiThread(new Runnable() {
@Override
public void run() {
mAdapter.notifyDataSetChanged();
}
});
}
答案 2 :(得分:11)
您不必创建新的适配器来更新ListView的内容。只需将您的适配器存储在一个字段中,并使用以下代码更新您的列表:
mAdapter.setList(yourNewList);
mAdapter.notifyDataSetChanged();
为了澄清这一点,您的活动应该是这样的:
private YourAdapter mAdapter;
protected void onCreate(...) {
...
mAdapter = new YourAdapter(this);
setListAdapter(mAdapter);
updateData();
}
private void updateData() {
List<Data> newData = getYourNewData();
mAdapter.setList(yourNewList);
mAdapter.notifyDataSetChanged();
}
答案 3 :(得分:3)
我也尝试过invalidate(),invalidateViews(),notifyDataSetChanged()。它们都可能在某些特定环境中起作用,但在我的情况下它不起作用。
在我的情况下,我不得不在列表中添加一些新行,它只是不起作用。创建新适配器解决了这个问题。
在调试时,我意识到数据存在,但只是没有渲染。如果invalidate()或invalidateViews()不呈现(它应该是),我不知道会发生什么。
创建一个新的Adapter对象来刷新修改过的数据似乎并不是一个坏主意。绝对有效。唯一的缺点可能是为您的适配器分配新内存所消耗的时间,但这应该是好的,假设Android系统足够智能并负责保持其效率。
如果你从方程式中取出这个,那么流程几乎与调用notifyDataSetChanged相同。从某种意义上说,在任何一种情况下都会调用相同的适配器函数集。
所以我们并没有太多损失,而是获得了很多。
答案 4 :(得分:3)
我认为用不同的数据重新填充相同的适配器将是更多或更好的技术。 将此方法放在具有right参数的Adapter类中(在我的情况下,您要显示为名称的数据列表) 调用此处更新列表数据的更新列表(在我的情况下为名称)
public void refill(ArrayList<BeanDatabase> names) {
list.clear();
list.addAll(names);
list.notifyDataSetChanged();
}
如果在列表更新时更改适配器或反复设置适配器,则强制关闭错误肯定会在某些时候引起问题。 (错误:列表数据已更新,但适配器未通知列表视图)
答案 5 :(得分:2)
我正在使用invalidateViews()做同样的事情,这对我有用。如果您希望它立即失效,您可以在调用invalidateViews后尝试调用postInvalidate。
答案 6 :(得分:1)
通过以下代码更新ListView的内容:
listViewBuddy = (ListView)findViewById(R.id.listViewBuddy);
mBuddyAdapter = new BuddyAdapter();
listViewBuddy.setAdapter(mBuddyAdapter);
<强>的onCreate()强>:
mBuddyAdapter.setData(buddyList);
mBuddyAdapter.notifyDataSetChanged();
onDataGet (在网络服务调用之后或从本地数据库或其他地方):
private class BuddyAdapter extends BaseAdapter {
private ArrayList<BuddyModel> mArrayList = new ArrayList<BuddyModel>();
private LayoutInflater mLayoutInflater= (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
private ViewHolder holder;
public void setData(ArrayList<BuddyModel> list){
mArrayList = list;
}
@Override
public int getCount() {
return mArrayList.size();
}
@Override
public BuddyModel getItem(int position) {
return mArrayList.get(position);
}
@Override
public long getItemId(int pos) {
return pos;
}
private class ViewHolder {
private TextView txtBuddyName, txtBuddyBadge;
}
@SuppressLint("InflateParams")
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null) {
holder = new ViewHolder();
convertView = mLayoutInflater.inflate(R.layout.row_buddy, null);
// bind views
holder.txtBuddyName = (TextView) convertView.findViewById(R.id.txtBuddyName);
holder.txtBuddyBadge = (TextView) convertView.findViewById(R.id.txtBuddyBadge);
// set tag
convertView.setTag(holder);
} else {
// get tag
holder = (ViewHolder) convertView.getTag();
}
holder.txtBuddyName.setText(mArrayList.get(position).getFriendId());
int badge = mArrayList.get(position).getCount();
if(badge!=0){
holder.txtBuddyBadge.setVisibility(View.VISIBLE);
holder.txtBuddyBadge.setText(""+badge);
}else{
holder.txtBuddyBadge.setVisibility(View.GONE);
}
return convertView;
}
}
<强> BaseAdapter 强>:
mBuddyAdapter.setData(Your_Updated_ArrayList);
mBuddyAdapter.notifyDataSetChanged();
每当您希望更新Listview 时,只需拨打以下两行代码:
public boolean isExtraHour(final ZonedDateTime time) {
final ZoneOffsetTransition dayTransition = time.getZone().getRules()
.getTransition(time.toLocalDateTime());
return dayTransition != null && dayTransition.isOverlap() && dayTransition.getInstant()
.equals(time.toInstant());
}
完成强>
答案 7 :(得分:1)
每次只有这对我有用,请注意我不知道是否会导致任何其他并发症或性能问题:
private void updateListView(){
listview.setAdapter(adapter);
}
答案 8 :(得分:0)
另一种简单方法:
//In your ListViewActivity:
public void refreshListView() {
listAdapter = new ListAdapter(this);
setListAdapter(listAdapter);
}