【问题标题】:Android: how to refresh ListView contents?Android:如何刷新 ListView 内容?
【发布时间】:2011-06-21 16:26:14
【问题描述】:

我的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();
}

【问题讨论】:

  • 你找到这个问题的答案了吗?我遇到了完全相同的问题。
  • 我也有同样的问题,有人解决了吗?
  • 任何人请帮助我如何使用现有数据 onscrolllistener 更新新的 listdata

标签: android listview android-adapter


【解决方案1】:

对于那些仍然有问题的人,我是这样解决的:

List<Item> newItems = databaseHandler.getItems();
ListArrayAdapter.clear();
ListArrayAdapter.addAll(newItems);
ListArrayAdapter.notifyDataSetChanged();
databaseHandler.close();

我先从适配器清除数据,然后添加新的项目集合,然后才设置notifyDataSetChanged(); 起初我并不清楚,所以我想指出这一点。请注意,如果不调用 notifyDataSetChanged(),视图将不会更新。

【讨论】:

  • 这帮助很大!我的问题是我再次创建了一个新的空 ListAdapter 而不是 ListArrayAdapter.clear();,因此其他解决方案都不起作用。
  • 我猜 dbh 是数据库处理程序 @akhyar 的一个实例
  • 测试并可能摆脱静态,子类并实现回收
  • 如果您在 clear()addAll() 方法中执行 notifyDataSetChanged(),它甚至可以工作。
【解决方案2】:

据我了解,如果你想在数据发生变化时立即刷新ListView,你应该在RunOnUiThread()中调用notifyDataSetChanged()

private void updateData() {
    List<Data> newData = getYourNewData();
    mAdapter.setList(yourNewList);

    runOnUiThread(new Runnable() {
        @Override
        public void run() {
                mAdapter.notifyDataSetChanged();
        }
    });
}

【讨论】:

  • 我已经梳理了两个小时StackOverflow,发现只有数百个无用的“调用notifyDataSetChanged”建议之类的。但是,您的答案确实有效。谢谢!
  • 是说mAdapter应该是final的?
  • @FarazAhmad 如果 mAdapter 是局部变量,它应该是最终的,但如果 mAdapter 是实例(活动)变量,它不必是 :)
  • 在 SO 上尝试了许多其他解决方案!这个工作完美!非常感谢@Aigori!
【解决方案3】:

您不必创建新的适配器来更新 ListView 的内容。只需将您的适配器存储在一个字段中并使用以下代码更新您的列表:

mAdapter.setList(yourNewList);
mAdapter.notifyDataSetChanged();

为了澄清这一点,您的 Activity 应如下所示:

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();
}

【讨论】:

  • 嗯,这段代码应该可以工作,你能发布你设置适配器和 setList() 方法的部分吗?
  • 所以,如果我的 ListActivity 设置为全屏 (style/Theme.NoBackground),它就会出现我描述的问题。但如果我将它设置为 Dialog 主题,它会正确刷新。
  • 好吧,适配器的设置如我原来的帖子所示,使用 setAdapter(...) 方法。而我的 setList() 方法并没有做任何有趣的事情,它只是设置了适配器的一个成员变量,用于确定每一行的视图。
  • @ab11 正如我已经说过的,您没有在updateData() 方法中设置适配器。而是将其设置为 onCreate() 并调用我在该适配器上的帖子中描述的那些方法。
  • 谢谢。对不起,我也试过这个。 (这就是“......我试过这个但没有成功......”的意思),但我意识到评论很模糊。
【解决方案4】:

我认为用不同的数据重新填充同一个适配器会是更多或最好的技术。 将此方法放入带有正确参数的 Adapter 类中(在我的情况下,您要显示为名称的数据列表) 在你用更新的列表(在我的例子中是名称)更新列表数据的地方调用它

public void refill(ArrayList<BeanDatabase> names) {
    list.clear();
    list.addAll(names);
    list.notifyDataSetChanged();
}

如果您更改适配器或在列表更新时一次又一次地设置适配器,那么强制关闭错误肯定会在某些时候导致问题。 (错误:列表数据已更新,但适配器未通知列表视图)

【讨论】:

    【解决方案5】:

    我也尝试过 invalidate()、invalidateViews()、notifyDataSetChanged()。它们都可能在某些特定情况下起作用,但在我的情况下并没有起作用。

    就我而言,我不得不在列表中添加一些新行,但它不起作用。创建一个新的适配器解决了这个问题。

    在调试时,我意识到数据在那里但没有呈现。如果 invalidate() 或 invalidateViews() 不渲染(它应该这样),我不知道会发生什么。

    创建一个新的 Adapter 对象来刷新修改过的数据似乎不是一个坏主意。它绝对有效。唯一的缺点可能是为您的适配器分配新内存所消耗的时间,但如果 Android 系统足够智能并且会处理好这一点以保持高效,那应该没问题。

    如果不考虑这个,流程几乎与调用 notifyDataSetChanged 相同。从某种意义上说,在任何一种情况下都会调用同一组适配器函数。

    所以我们并没有失去很多,而是得到了很多。

    【讨论】:

    • 我发现为列表视图设置背景颜色消除了我的很多刷新问题。
    【解决方案6】:

    我正在使用 invalidateViews() 做同样的事情,这对我有用。如果您希望它立即失效,您可以在调用 invalidateViews 后尝试调用 postInvalidate。

    【讨论】:

      【解决方案7】:

      更新 ListView 的内容,通过以下代码:

      private ListView listViewBuddy;
      private BuddyAdapter mBuddyAdapter;
      private ArrayList<BuddyModel> buddyList = new ArrayList<BuddyModel>();
      

      onCreate()

      listViewBuddy = (ListView)findViewById(R.id.listViewBuddy);
      mBuddyAdapter = new BuddyAdapter();
      listViewBuddy.setAdapter(mBuddyAdapter);
      

      onDataGet(在 web 服务调用后或从本地数据库或其他):

      mBuddyAdapter.setData(buddyList);
      mBuddyAdapter.notifyDataSetChanged();
      

      BaseAdapter

      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;
          }
      }
      

      每当你想更新列表视图只需调用以下两行代码:

       mBuddyAdapter.setData(Your_Updated_ArrayList);
       mBuddyAdapter.notifyDataSetChanged();
      

      完成

      【讨论】:

        【解决方案8】:

        只有这对我每次都有效,请注意我不知道它是否会导致任何其他并发症或性能问题:

        private void updateListView(){
                listview.setAdapter(adapter);
            }
        

        【讨论】:

          【解决方案9】:

          另一种简单的方法:

          //In your ListViewActivity:
          public void refreshListView() {
              listAdapter = new ListAdapter(this);
              setListAdapter(listAdapter);
          }
          

          【讨论】:

            猜你喜欢
            • 2014-06-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多