【问题标题】:Android RecyclerView does not update on data changedAndroid RecyclerView 不会更新数据更改
【发布时间】:2017-08-31 09:09:33
【问题描述】:

RecyclerView 仅显示创建时 ArrayList(适配器的数据)中的项目。我添加更多行的所有尝试似乎都有效,但列表保留了初始数据。 它不是重复的,因为我尝试了在谷歌上找到的所有建议。 我已经做了什么:

  • adapter.notifyDataSetChanged();
  • adapter.notifyItemChanged(5);
  • recycleList.invalidate();
  • recycleList.setAdapter(适配器);
  • 使用 Handler 在 UIThread 上运行更新

适配器正常工作 - onCreateView 可以正常工作(创建新行)以及 onBindView(绑定新数据)。 getItemCount() 返回正确的值(更新后更大)。一切看起来应该是 - 而不是最终视图 - 没有改变。

唯一可行的方法是使用新数据集从头开始重新创建适配器 - 设计上完全不可接受(长列表很难看)。

代码如下:

在片段中创建:

adapter = new MyListAdapter(getContext());
adapter.addItems(initialItems); // These and only these I see on the list
LinearLayoutManager mLayoutManager=new LinearLayoutManager(getContext());
recycleList.setLayoutManager(mLayoutManager);
recycleList.setAdapter(adapter);

尝试从片段更新:

public void onUpdateReady(ArrayList<Model> freshData) {
    new Handler(Looper.getMainLooper()).post(new Runnable() {
        @Override
        public void run() { // UI thread
            adapter.addItems(freshData);
            adapter.notifyDataSetChanged();
            adapter.notifyItemChanged(5);
            recycleList.invalidate();
            //notifyItemRangeInserted(3,freshData.size());
        }
    });
}

适配器:

private Context mContext;
private ArrayList<Model> data;

public MyListAdapter(Context mContext) {
    this.mContext = mContext;
    data=new ArrayList<>();
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    LayoutInflater inflater = LayoutInflater.from(mContext);
    View view = inflater.inflate(R.layout.list_item, parent, false);
    return new ViewHolder(view);
}

@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {        
    viewHolder.textName.setText(data.get(position).getName());
}

@Override
public int getItemCount() {
    return data.size();
}

public void addItems(Collection<Model> list) {
    data.addAll(list);
}

public class ViewHolder extends RecyclerView.ViewHolder {
    @BindView(R.id.textName) TextView textName;

    public ViewHolder(View itemView) {
        super(itemView);
        ButterKnife.bind(this,itemView);
    }
}

更新:根据 cmets 更改:

public void addItems(Collection<Model> list) {
    ArrayList<Model> newData=new ArrayList<>(); // Make new array
    newData.addAll(data); // Take old
    newData.addAll(list); // Add new
    data=newData; // change to data to newly created array
    notifyDataSetChanged();
}

【问题讨论】:

  • 在这里看看我的回答:stackoverflow.com/a/38568013/5223744
  • 不要将项目直接添加到您的适配器,将项目添加到 arraylist 并将该列表传递给您的适配器,以及每当您调用 adapter.notifyDataSetChanged();它将反映到您的回收站视图
  • 之前的评论有误。你有相同的arraylist 地址。不需要在类之外重新分配值。
  • 照你说的做了。更改了 addItems(请参阅帖子中的更新)。但不幸的是,没有任何改变。仍然看到旧行 - 即使我执行 data.clear() - 初始行仍然没有数据。换句话说 - 没有更新。
  • getItemCount 会在notifyDataSetChanged() 之后被解雇吗?

标签: android android-recyclerview notifydatasetchanged


【解决方案1】:
try this

In Fragment
ArrayList<Data> items=new ArrayList<>();

items.addAll(initialItems);
adapter = new MyListAdapter(getContext(),items);
LinearLayoutManager mLayoutManager=new LinearLayoutManager(getContext());
recycleList.setLayoutManager(mLayoutManager);
recycleList.setAdapter(adapter);


public void onUpdateReady(ArrayList<Model> freshData) {
    new Handler(Looper.getMainLooper()).post(new Runnable() {
        @Override
        public void run() { // UI thread
            items.addAll(freshData);
            adapter.notifyDataSetChanged();
            followList.invalidate();

        }
    });
}



private Context mContext;
private ArrayList<Model> data;

public MyListAdapter(Context mContext,ArrayList<Model> data) {
    this.mContext = mContext;
    this.data=data;
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    LayoutInflater inflater = LayoutInflater.from(mContext);
    View view = inflater.inflate(R.layout.list_item, parent, false);
    return new ViewHolder(view);
}

@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {        
    viewHolder.textName.setText(data.get(position).getName());
}

@Override
public int getItemCount() {
    return data.size();
}


public class ViewHolder extends RecyclerView.ViewHolder {
    @BindView(R.id.textName) TextView textName;

    public ViewHolder(View itemView) {
        super(itemView);
        ButterKnife.bind(this,itemView);
    }
}

【讨论】:

    【解决方案2】:

    更改您的适配器构造函数:

    private ArrayList<Model> data;
    public MyListAdapter(Context mContext,ArrayList<Model> data) {
    this.mContext = mContext;
    this.data = data;}
    
    public void addItems(Collection<Model> list) {
    data.addAll(list);
     }
    

    片段:

    adapter = new MyListAdapter(getContext(),initialItems);
    

    【讨论】:

    • 相同的结果 :-(
    【解决方案3】:

    我曾经遇到过类似的问题,并且在 ListView 上调用 invalidateViews 有效,即使它是一个 hack。而不是recycleList.invalidate(); 尝试recycleList.invalidateViews();

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-31
      • 1970-01-01
      • 2018-04-20
      • 1970-01-01
      • 2016-04-21
      • 2023-03-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多