【问题标题】:notifyDataSetChanged() makes the list refresh and scroll jumps back to the topnotifyDataSetChanged() 使列表刷新并滚动跳回顶部
【发布时间】:2013-07-15 18:12:17
【问题描述】:

我正在尝试实现无限滚动列表视图,但是当我调用 notifyDataSetChanged() 时,整个列表都会刷新,然后滚动位置会回到顶部。

这是正常行为吗?我怎样才能让它简单地添加添加的项目而不刷新并保持滚动位置?

【问题讨论】:

  • 你能发布你的完整代码吗?

标签: java android android-listview


【解决方案1】:

这样的行为是不正常的。在没有看到您的代码的情况下,我可以建议以下内容:

1) 您没有从 UI 线程调用 notifyDataSetChanged()。正确方法:

runOnUiThread(new Runnable() {
    public void run() {
        adapter.notifyDataSetChanged();
    }
});

2) 你不小心拨打了adapter.notifyDataSetInvalidated();

3) 在您的适配器中,您覆盖adapter.notifyDataSetChanged(); 方法并添加指令以转到顶部

4) 如果您使用列表来填充适配器 - 您每次都提供新列表,因此适配器设置会被刷新。您应该始终提供相同的列表。但是,您可以根据需要更改它。如果您要重置列表,请使用 list.clear 而不是 list = new ArrayList();

这是我的适配器的一个示例:

public class Adapter extends BaseAdapter {

    private Activity activity;
    private ArrayList<HashMap<String, String>> data;
    private static LayoutInflater inflater = null;
    public ImageLoader imageLoader;

    public MediaItemAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
        activity = a;
        data = d;
        inflater = (LayoutInflater) activity
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        imageLoader = new ImageLoader(activity.getApplicationContext());
    }

    public int getCount() {
        return data.size();
    }

    public Object getItem(int position) {
        return position;
    }

    public long getItemId(int position) {
        return position;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        View vi = convertView;
        if (convertView == null) {
            vi = inflater.inflate(R.layout.item_composer, null);
        }
        TextView title = (TextView) vi.findViewById(R.id.item_title); // title
        TextView price = (TextView) vi.findViewById(R.id.price);


        return vi;
    }


}

调用适配器:

List myList = new ArrayList<HashMap<String, String>>();
Adapter ma = new Adapter(this, myList);

myList 在适配器初始化之前可以为空。

然后对我的列表做一些操作:

myList.add(someElement);
ma.notifyDataSetChanged();

如果您需要删除所有项目:

myList.clear();
ma.notifyDataSetChanged();

这样的实现是无穷无尽的,我看到超过 15000 个元素没有任何问题。

【讨论】:

  • 就我而言,这是第三个问题。我正在填充一个全新的列表并将其分配给最初与适配器一起使用的变量,因为适配器中的列表从未被刷新。
  • 好帖子!拯救了我的理智!
  • 就我而言,我一次又一次地设置适配器。不,如果您的适配器已经设置为列表视图,只需通知它。
  • +1 用于添加 ma.notifyDataSetChanged(); 您刚刚使我的回收站免于挂起,现在剩下的就是在刷新之前完全停止使用 araylist.clear()。我认为最好的解决方案是使用DiffUtils
【解决方案2】:

就我而言,问题是每次设置新数据时我都会调用ListView.setAdapter(adapter),这也会重置位置并且视图会跳到顶部。

删除多余的 setAdapter(...) 调用为我修复了它。

【讨论】:

    【解决方案3】:

    你可以用另一种方式来做,像这样

    int position = scrollView.getSelectedItemPosition();
    notifyDataSetChanged();
    scrollView.setSelection(position);
    

    【讨论】:

    • 这不是正确的方法,但有时非常有用!
    【解决方案4】:

    如果您的适配器是ArrayList 的子类,那么调用adapter.clear() 将调用notifyDataSetChanged() 导致滚动位置丢失。考虑先致电setNotifyOnChange(false) 以防止这种情况发生。

    更多信息在这里:https://stackoverflow.com/a/14719538/383761

    【讨论】:

      【解决方案5】:

      @Yarth 的回答有帮助 我将添加一个我刚刚发现导致此问题的小问题, 如果你打电话

      listview.setVisibility(View.VISIBLE);
      

      还会使整个列表滚动到顶部。

      【讨论】:

        【解决方案6】:

        遇到同样的问题,发现是因为我在拨打notifyDataSetChanged()时不小心再次设置了recyclerview的layoutManager

        将 layoutManager 实例保留在 recyclerview 上可以解决此问题。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-10-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-02-10
          • 1970-01-01
          • 2011-07-16
          相关资源
          最近更新 更多