如何让 RecyclerView 停止回收定义的位置?
How to make RecyclerView stops recycling defined positions?
我的问题是:我在 RecyclerView 中的一个视图上发生了视频流。
当用户滚动时,视图将被回收,并且其他相机会在该回收的取景器上开始自己的流式传输。这对用户界面不利,因为流式传输过程需要几秒钟才能开始。
如何对 RecyclerView 说:"Hey Recycler, please, do not recycle that exact position x and give that position ALWAYS the same viewholder you gave it the first time, instead of random one"?
请有人帮助我=(
如果你正在使用查询,你可以使用
query.limit(//no of items you want to show in your RecyclerView)
试一试。
或请post您的查询代码
在 ViewHolder
上执行 viewHolder.setIsRecyclable(false)
您希望 不 被回收。
来自docs of ViewHolder#setIsRecyclable(boolean):
Informs the recycler whether this item can be recycled. Views which are not recyclable will not be reused for other items until setIsRecyclable() is later set to true.
这将导致只创建一个 ViewHolder
。
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
...
@Override
public void onViewAttachedToWindow(final RecyclerView.ViewHolder holder) {
if (holder instanceof VideoViewHolder) {
holder.setIsRecyclable(false);
}
super.onViewAttachedToWindow(holder);
}
@Override
public void onViewDetachedFromWindow(final RecyclerView.ViewHolder holder) {
if (holder instanceof VideoViewHolder){
holder.setIsRecyclable(true);
}
super.onViewDetachedFromWindow(holder);
}
...
}
您的问题来自取景器本身。 Viewholders 保留对视图的引用,而适配器则不。适配器仅保留数据集合。因此,向 viewholder 添加一个字段以保留对用于在 viewholder 中填充视图的数据元素的引用。也就是说:
public class SomeViewHolder extends RecyclerView.ViewHolder{
private View view;
private Data data;
public SomeViewHolder(View itemView) {
super(itemView);
view = itemView;
}
public void bindData(Data data){
view.setData(data);
this.data = data;
}
public void setData(Data data){
this.data = data;
}
public Data getData(){
return data;
}
public View getView(){
return view;
}
}
现在,viewholder 知道适配器的哪个元素正在使用。因此,在adapter中覆盖绑定方法时,可以检查holder是否已经绑定了一些数据,如果数据中包含video,则可以避免绑定并强制设置一个已经加载的视图。
@Override
public void onBindViewHolder(SomeViewHolder holder, int position) {
//videoViewData is a data field you have to put into the adapter.
//videoView is a view field you have to put into the adapter.
if(adapterData.get(position).equals(videoViewData)){
holder.setView(videoView);
holder.setData(adapterData.get(position));
}else{
holder.bindData(adapterData.get(position));
if(adapterData.get(position).isVideo()){
videoViewData = adapterData.get(position);
videoView = holder.getView();
}
}
}
最后,您必须覆盖适配器中的 onViewRecycled 方法,因此,当包含视频的视图被回收时,您可以获取该视图并将其放在其他地方。
public void onViewRecycled(SomeViewHolder holder){
if(holder.getData().isVideo()){
videoViewData = holder.getData().
videoView = holder.getView();
videoView.pauseVideo();
}
}
请记住,如果您不管理存储的视图,这可能会导致一些严重的泄漏。此外,您必须定义用于判断数据何时为视频的方法,以及正确定义的 equals 方法。
尝试将此用于特定位置:
holder.setIsRecyclable(false);
希望这可能有所帮助。
在您的 getItemViewType(int position)
适配器方法中,为每个视频分配唯一值,因此它将始终 return 相同视频的相同 ViewHolder,如您所愿。
- return 唯一正数作为每种视频类型的类型(这里我使用适配器位置作为唯一键)
- return 任何非视频项目的负数。 (这里没有什么特别的,只是为了避免与视频项目冲突,我们对非视频项目使用负数)
我希望你明白了。干杯:)
@Override
public int getItemViewType(int position) {
// Just as an example, return 0 or 2 depending on position
// Note that unlike in ListView adapters, types don't have to be contiguous
if(dataList.get(position).isVideo()){
return position;
}else{
return -1;//indicates general type, if you have more types other than video, you can use -1,-2,-3 and so on.
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case -1: View view1 = LayoutInflater.from(parent.getContext())
.inflate(R.layout.general_item, parent, false);
return new GeneralViewHolder(view1);
default:View view2 = LayoutInflater.from(parent.getContext())
.inflate(R.layout.video_item, parent, false);
return new VideoViewHolder(view2);
}
}
RecyclerView 多次使用一个视图,当它包含一次没有显示在屏幕上的列表时(意味着一个列表包含大量没有同时显示在屏幕上的项目,你需要向上滚动和向下)。当用户滚动列表时,屏幕外的项目将被重新使用以显示剩余的列表项目,这称为回收。
要停止回收项目,请在您的 onBindViewHolder 方法中调用此方法:
viewHolder.setIsRecyclable(false);
此声明停止回收视图。
要开始回收项目,请在您的 onBindViewHolder 方法中调用此方法:
viewHolder.setIsRecyclable(true);
希望这能解决您的问题。
谢谢
在 recyclerview 中处理不回收物品的最佳方法此答案将解决您的问题。
我的问题是:我在 RecyclerView 中的一个视图上发生了视频流。
当用户滚动时,视图将被回收,并且其他相机会在该回收的取景器上开始自己的流式传输。这对用户界面不利,因为流式传输过程需要几秒钟才能开始。
如何对 RecyclerView 说:"Hey Recycler, please, do not recycle that exact position x and give that position ALWAYS the same viewholder you gave it the first time, instead of random one"?
请有人帮助我=(
如果你正在使用查询,你可以使用
query.limit(//no of items you want to show in your RecyclerView)
试一试。
或请post您的查询代码
在 ViewHolder
上执行 viewHolder.setIsRecyclable(false)
您希望 不 被回收。
来自docs of ViewHolder#setIsRecyclable(boolean):
Informs the recycler whether this item can be recycled. Views which are not recyclable will not be reused for other items until setIsRecyclable() is later set to true.
这将导致只创建一个 ViewHolder
。
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
...
@Override
public void onViewAttachedToWindow(final RecyclerView.ViewHolder holder) {
if (holder instanceof VideoViewHolder) {
holder.setIsRecyclable(false);
}
super.onViewAttachedToWindow(holder);
}
@Override
public void onViewDetachedFromWindow(final RecyclerView.ViewHolder holder) {
if (holder instanceof VideoViewHolder){
holder.setIsRecyclable(true);
}
super.onViewDetachedFromWindow(holder);
}
...
}
您的问题来自取景器本身。 Viewholders 保留对视图的引用,而适配器则不。适配器仅保留数据集合。因此,向 viewholder 添加一个字段以保留对用于在 viewholder 中填充视图的数据元素的引用。也就是说:
public class SomeViewHolder extends RecyclerView.ViewHolder{
private View view;
private Data data;
public SomeViewHolder(View itemView) {
super(itemView);
view = itemView;
}
public void bindData(Data data){
view.setData(data);
this.data = data;
}
public void setData(Data data){
this.data = data;
}
public Data getData(){
return data;
}
public View getView(){
return view;
}
}
现在,viewholder 知道适配器的哪个元素正在使用。因此,在adapter中覆盖绑定方法时,可以检查holder是否已经绑定了一些数据,如果数据中包含video,则可以避免绑定并强制设置一个已经加载的视图。
@Override
public void onBindViewHolder(SomeViewHolder holder, int position) {
//videoViewData is a data field you have to put into the adapter.
//videoView is a view field you have to put into the adapter.
if(adapterData.get(position).equals(videoViewData)){
holder.setView(videoView);
holder.setData(adapterData.get(position));
}else{
holder.bindData(adapterData.get(position));
if(adapterData.get(position).isVideo()){
videoViewData = adapterData.get(position);
videoView = holder.getView();
}
}
}
最后,您必须覆盖适配器中的 onViewRecycled 方法,因此,当包含视频的视图被回收时,您可以获取该视图并将其放在其他地方。
public void onViewRecycled(SomeViewHolder holder){
if(holder.getData().isVideo()){
videoViewData = holder.getData().
videoView = holder.getView();
videoView.pauseVideo();
}
}
请记住,如果您不管理存储的视图,这可能会导致一些严重的泄漏。此外,您必须定义用于判断数据何时为视频的方法,以及正确定义的 equals 方法。
尝试将此用于特定位置:
holder.setIsRecyclable(false);
希望这可能有所帮助。
在您的 getItemViewType(int position)
适配器方法中,为每个视频分配唯一值,因此它将始终 return 相同视频的相同 ViewHolder,如您所愿。
- return 唯一正数作为每种视频类型的类型(这里我使用适配器位置作为唯一键)
- return 任何非视频项目的负数。 (这里没有什么特别的,只是为了避免与视频项目冲突,我们对非视频项目使用负数)
我希望你明白了。干杯:)
@Override
public int getItemViewType(int position) {
// Just as an example, return 0 or 2 depending on position
// Note that unlike in ListView adapters, types don't have to be contiguous
if(dataList.get(position).isVideo()){
return position;
}else{
return -1;//indicates general type, if you have more types other than video, you can use -1,-2,-3 and so on.
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case -1: View view1 = LayoutInflater.from(parent.getContext())
.inflate(R.layout.general_item, parent, false);
return new GeneralViewHolder(view1);
default:View view2 = LayoutInflater.from(parent.getContext())
.inflate(R.layout.video_item, parent, false);
return new VideoViewHolder(view2);
}
}
RecyclerView 多次使用一个视图,当它包含一次没有显示在屏幕上的列表时(意味着一个列表包含大量没有同时显示在屏幕上的项目,你需要向上滚动和向下)。当用户滚动列表时,屏幕外的项目将被重新使用以显示剩余的列表项目,这称为回收。
要停止回收项目,请在您的 onBindViewHolder 方法中调用此方法:
viewHolder.setIsRecyclable(false);
此声明停止回收视图。
要开始回收项目,请在您的 onBindViewHolder 方法中调用此方法:
viewHolder.setIsRecyclable(true);
希望这能解决您的问题。 谢谢
在 recyclerview 中处理不回收物品的最佳方法此答案将解决您的问题。