【问题标题】:How to Update the Views of the RecyclerView - without Passing a Copy of the Data如何在不传递数据副本的情况下更新 RecyclerView 的视图
【发布时间】:2018-08-16 23:36:32
【问题描述】:

我想每 30 秒更新一次 RecyclerView 视图的视图。我用这个语句:

adapter.notifyItemRangeChanged(0, channelsInGroup.size());

它不起作用。我可以通过将内容复制到新的数组列表,将新的数组列表传递给适配器,然后清空来让它工作 新的arraylist并在更新后重新填充它,最后调用notifyItemRangeChanged

channelsInGroup.clear();

g = channelsLab.getGroupByTitle(mGroupTitle)
List<Channel> channelListNew = new ArrayList<Channel>();
for (Channel c : g.getChannels()) {
    channelListNew.add(c);
}

channelsInGroup.addAll(channelListNew);
adapter.notifyItemRangeChanged(0, channelsInGroup.size());

如何在不传递数组列表副本的情况下更新 RecyclerView 中的视图?我想使用定期更新的原始g.getChannels()

相关代码sn-ps:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    mRootView = inflater.inflate(R.layout.fragment_channel_epg, container, false);

    RecyclerView recyclerView = mRootView.findViewById(R.id.recyclerView);
    LinearLayoutManager horizontalLayoutManagaer
            = new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false);
    recyclerView.setLayoutManager(horizontalLayoutManagaer);

    adapter = new MyRecyclerViewAdapter(getContext(), channelsInGroup);
    recyclerView.setAdapter(adapter);

    return mRootView;
}

public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder> {

    private List<Channel> mChannelsList;
    private LayoutInflater mInflater;

    MyRecyclerViewAdapter(Context context, List<Channel> channelList) {
        this.mInflater = LayoutInflater.from(context);
        this.mChannelsList = channelList;
    }

    @Override
    @NonNull
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = mInflater.inflate(R.layout.epg_row_of_playing_channel, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        if (mChannelsList.get(position).getProgrammeListNext24Hours() != null) {
           holder.myTextView.setText(mChannelsList.get(position).getProgrammeListNext24Hours().get(0).getTitle().get(0));
        }
        else {
            holder.myTextView.setText("yok");
        }
    }

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

    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        TextView myTextView;

        ViewHolder(View itemView) {
            super(itemView);
            myTextView = itemView.findViewById(R.id.programme_description_in_epg_bar);
        }
    }
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    channelsLab = ChannelsLab.get(BKD_ChannelEPGFragment.this.getContext());
    g = channelsLab.getGroupByTitle(mGroupTitle);
    channelsInGroup = g.getChannels();

}

【问题讨论】:

  • 我想定期更新我的 RecyclerView 视图。比如多久一次?
  • 每 30 秒...

标签: android android-recyclerview android-viewholder


【解决方案1】:

如果您想为新旧列表之间的更改设置动画,那么您可以使用DiffUtil 而无需调用任何notify 方法。创建一个扩展 DiffUtil.Callback 的类,如下所示。

public class MyDiffCallback extends DiffUtil.Callback {

    List<Channel> oldList;
    List<Channel> newList;

    MyDiffCallback(List<Channel> oldList, List<Channel> newList) {
        oldList = this.oldList;
        newList = this.newList;
    }

    public int getOldListSize() {
        return oldList.size;
    }

    public int getNewListSize() {
        return newList.size;
    }

    @Override
    public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
        // If you have an id for the data then it should be used here.
        return oldList.get(oldItemPosition).id == newList.get(newItemPosition).id;
    }

    @Override
    public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
        // Replace id with whatever is appropriate to check if the contents are the same.
        return oldList.get(oldItemPosition).id  == newList.get(newItemPosition).id;
    }
}

然后在适配器内部创建一个方法来计算差异并交换数据。

public void swap(List<Channel> channelList) {
    MyDiffCallback diffCallback = new MyDiffCallback(mChannelsList, channelList);
    DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(diffCallback);
    mChannelsList.clear();
    mChannelsList.addAll(channelList);
    diffResult.dispatchUpdatesTo(this);
}

现在您可以使用adapter.swap(newList),其中newList 应该包含新旧数据。

要在列表中添加新项目而不包括旧数据,只需从 swap() 中删除 mChannelsList.clear() 并为其提供要添加到列表中的新数据。

【讨论】:

  • 感谢您的回答,但我的问题是我是否必须每次都向适配器提供更新的数据副本。为什么在传递数据本身时它不起作用(在我的例子中是arraylist)?
【解决方案2】:

只需拨打adapter.notifyDataSetChanged()

【讨论】:

  • 滚动时冻结。我怀疑原因是数据正在同时更新......
猜你喜欢
  • 2019-05-12
  • 1970-01-01
  • 2020-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-06
  • 1970-01-01
相关资源
最近更新 更多