I have a RecyclerView in which the user can drag and drop an item to a different position in the RecyclerView.
So far everything works fine.
My problem begins when the RecyclerView has more items than it can display. 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. The user just see the old positions for the items.
You can see this issue in the .gif below.
I already tried several things out like:
recyclerViewItem.getRecycledViewPool().setMaxRecycledViews(0,0);
recyclerViewItem.setItemViewCacheSize(30);
and
holder.setIsRecyclable(false);
inside of my onBindViewHolder.
But nothing seems to work for me.
Does anyone know a solution for this problem?
My Fragment 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:
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);
}
}
