简体   繁体   English

Android Recycler查看防止回收所有物品

[英]Android RecyclerView prevent recycling all items

I have a RecyclerView in which the user can drag and drop an item to a different position in the RecyclerView.我有一个 RecyclerView,用户可以在其中将项目拖放到 RecyclerView 中的不同 position。

So far everything works fine.到目前为止一切正常。

My problem begins when the RecyclerView has more items than it can display.当 RecyclerView 的项目多于显示时,我的问题就开始了。 So when it recycle his content .所以当它回收他的内容时。 When the user drag and drop an item to a different position and than scroll away from this part the position changes are not saved.当用户将项目拖放到不同的 position 并从该部分滚动离开时,不会保存 position 更改。 The user just see the old positions for the items.用户只看到项目的旧位置。

You can see this issue in the.gif below.您可以在下面的 .gif 中看到这个问题。

在此处输入图像描述

I already tried several things out like:我已经尝试了几件事,例如:

    recyclerViewItem.getRecycledViewPool().setMaxRecycledViews(0,0);
        
recyclerViewItem.setItemViewCacheSize(30);

and

holder.setIsRecyclable(false);

inside of my onBindViewHolder.在我的 onBindViewHolder 里面。

But nothing seems to work for me.但似乎没有什么对我有用。

Does anyone know a solution for this problem?有谁知道这个问题的解决方案?

My Fragment class:我的片段 class:

public class ShoppinglistFragment extends Fragment {

private ViewModel viewModel;
private ShoppinglistAdapter adapterShoppingItem = new ShoppinglistAdapter();
private RecyclerView recyclerViewItem;
private Boolean fragmentStarted = false;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.shoppinglist_layout, container, false);
    recyclerViewItem = view.findViewById(R.id.recyclerViewShoppinglist);
    return view;
}

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

    viewModel = ViewModelProviders.of(getActivity()).get(ViewModel.class);
    
    fragmentStarted = true;

    recyclerViewItem.setLayoutManager(new LinearLayoutManager(getContext()));
    recyclerViewItem.setHasFixedSize(false);
    recyclerViewItem.getRecycledViewPool().setMaxRecycledViews(0,0);
    recyclerViewItem.setItemViewCacheSize(30);
    recyclerViewItem.setAdapter(adapterShoppingItem);

    ItemTouchHelper.Callback callback =
            new ItemMoveCallback(adapterShoppingItem);
    ItemTouchHelper touchHelper = new ItemTouchHelper(callback);
    touchHelper.attachToRecyclerView(recyclerViewItem);

    //fetch all Shoppinglist Items from local storage
    viewModel.getAllShoppinglistItems().observe((LifecycleOwner) this, new Observer <List<Shoppinglist>>() {
        @Override
        public void onChanged(@Nullable List<Shoppinglist> items) {

            if (fragmentStarted){
                adapterShoppingItem.submitList(items);

                fragmentStarted = false;
            }
        }
    });

    adapterShoppingItem.setOnPositionChanged(new ShoppinglistAdapter.onPositionChanged() {
        @Override
        public void onPositionChanged(Shoppinglist fromItem, Shoppinglist toItem, int fromPosition, int toPosition) {

            int fromPositionServer = fromItem.getPosition();
            int toPositionServer = toItem.getPosition();

            fromItem.setPosition(toPositionServer);
            toItem.setPosition(fromPositionServer);


            //updating Shoppinglist Item locally
            viewModel.updateItem(fromItem);
            viewModel.updateItem(toItem);

        }
    });
}

}} }}

and my Adapter class:和我的适配器 class:

public class ShoppinglistAdapter extends ListAdapter<Shoppinglist, ShoppinglistAdapter.NoteHolder> implements ItemMoveCallback.ItemTouchHelperContract {

public Integer ressourceType;
private onPositionChanged onPositionChanged;
private ArrayList<Shoppinglist> globalItemList = new ArrayList<Shoppinglist>();

public ShoppinglistAdapter() {
    super(DIFF_CALLBACK);
    Integer valueOf = Integer.valueOf(0);
    this.ressourceType = valueOf;
}

private static final DiffUtil.ItemCallback<Shoppinglist> DIFF_CALLBACK = new DiffUtil.ItemCallback<Shoppinglist>() {
    @Override
    public boolean areItemsTheSame(Shoppinglist oldItem, Shoppinglist newItem) {
        return oldItem.getSqlid() == newItem.getSqlid();
    }

    @Override
    public boolean areContentsTheSame(Shoppinglist oldItem, Shoppinglist newItem) {
        return oldItem.getTitle().equals(newItem.getTitle());
    }
};

@NonNull
@Override
public NoteHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View itemView = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.shoppinglist_item, parent, false);

    return new NoteHolder(itemView);
}

@Override
public void onBindViewHolder(@NonNull NoteHolder holder, int position) {
    Shoppinglist currentItem = getItem(position);
    
    holder.setIsRecyclable(false);

    holder.tv.setText(currentItem.getTitle());
    ...
}

public Shoppinglist getNoteAt(int position) {
    return getItem(position);
}

public class NoteHolder extends RecyclerView.ViewHolder {
    private TextView   tv;

    public NoteHolder(View itemView) {
        super(itemView);
        tv= itemView.findViewById(R.id.tv);
        globalItemList .add(currentNote);
    }
}

public interface onPositionChanged {
    void onPositionChanged(Shoppinglist fromItem, Shoppinglist toItem, int fromPosition, int toPosition);
}

public void setOnPositionChanged(ShoppinglistAdapter.onPositionChanged listener) {
    this.onPositionChanged = listener;
}

@Override
public void onRowMoved(int fromPosition, int toPosition) {

    //send switched Items to Fragment 
    onPositionChanged.onPositionChanged(globalItemList.get(fromPosition), globalItemList.get(toPosition), fromPosition, toPosition);

    //switch Items inside of the global Item List 
    Collections.swap(globalItemList, fromPosition, toPosition);
    
    notifyItemMoved(fromPosition, toPosition);
}

@Override
public void onRowSelected(NoteHolder myViewHolder) {}

@Override
public void onRowClear(NoteHolder myViewHolder) {}

@Override
public int getItemViewType(int position) {
    return super.getItemViewType(position);
}

} }

The problem is that you should swap items in ListAdapter.mDiffer which holds the current showing list.问题是您应该交换ListAdapter.mDiffer中的项目,它包含当前的显示列表。 So, globalItemList in your code is unused.因此,您的代码中的globalItemList未使用。 Replace onRowMoved of your adapter with the following one:将适配器的onRowMoved替换为以下内容:

@Override
public void onRowMoved(int fromPosition, int toPosition) {
    ArrayList<Shoppinglist> list = new ArrayList(getCurrentList());
    Collections.swap(list, fromPosition, toPosition);
    submitList(list);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM