I have a recyclerview list and I want to be able to move those items. When I use notifyDataSetChanged
() it works but, but if I use notifyItemMoved
(fromPosition, toPosition) it doesn't and app crashes.
Here is stacktrace:
java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.recyclerview.widget.RecyclerView$Recycler.unscrapView(androidx.recyclerview.widget.RecyclerView$ViewHolder)' on a null object reference
at androidx.recyclerview.widget.RecyclerView$ViewHolder.unScrap(RecyclerView.java:11235)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6166)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6118)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6114)
at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2303)
at androidx.recyclerview.widget.GridLayoutManager.layoutChunk(GridLayoutManager.java:561)
at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665)
at androidx.recyclerview.widget.GridLayoutManager.onLayoutChildren(GridLayoutManager.java:170)
at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4134)
at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3851)
at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4404)
at android.view.View.layout(View.java:23167)
at android.view.ViewGroup.layout(ViewGroup.java:6412)
at androidx.swiperefreshlayout.widget.SwipeRefreshLayout.onLayout(SwipeRefreshLayout.java:625)
at android.view.View.layout(View.java:23167)
at android.view.ViewGroup.layout(ViewGroup.java:6412)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1103)
at android.view.View.layout(View.java:23167)
at android.view.ViewGroup.layout(ViewGroup.java:6412)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
at android.view.View.layout(View.java:23167)
at android.view.ViewGroup.layout(ViewGroup.java:6412)
at androidx.constraintlayout.widget.ConstraintLayout.onLayout(ConstraintLayout.java:1873)
at android.view.View.layout(View.java:23167)
at android.view.ViewGroup.layout(ViewGroup.java:6412)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
at android.view.View.layout(View.java:23167)
at android.view.ViewGroup.layout(ViewGroup.java:6412)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
at android.view.View.layout(View.java:23167)
at android.view.ViewGroup.layout(ViewGroup.java:6412)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
at android.view.View.layout(View.java:23167)
at android.view.ViewGroup.layout(ViewGroup.java:6412)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
at android.view.View.layout(View.java:23167)
at android.view.ViewGroup.layout(ViewGroup.java:6412)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
at com.android.internal.policy.DecorView.onLayout(DecorView.java:812)
at android.view.View.layout(View.java:23167)
at android.view.ViewGroup.layout(ViewGroup.java:6412)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:3724)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3183)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2153)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8761)
2023-01-11 16:11:07.234 12095-12095/ab.cde.simplenotepad E/AndroidRuntime: at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1120)
at android.view.Choreographer.doCallbacks(Choreographer.java:926)
at android.view.Choreographer.doFrame(Choreographer.java:859)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1105)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:241)
at android.os.Looper.loop(Looper.java:358)
at android.app.ActivityThread.main(ActivityThread.java:8006)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1009)
Here is my code:
MyFragment.java
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
postponeEnterTransition();
initAds(view);
requireActivity().setTitle(getString(R.string.my_notes));
this.view = view;
notesList = db.getAllNotes();
configureRecyclerView(view, notesList);
ItemTouchHelper.SimpleCallback simpleCallback = new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.START | ItemTouchHelper.END, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
int fromPosition = viewHolder.getAdapterPosition();
int toPosition = target.getAdapterPosition();
notesList = db.getAllNotes();
if (fromPosition < toPosition) { // jeśli notka idzie w prawo albo w dół
db.updateOrder(notesList.get(toPosition).getNoteOrder(), notesList.get(fromPosition).getId());
for (int i = fromPosition; i <= toPosition - 1; i++) {
db.updateOrder(notesList.get(i).getNoteOrder(), notesList.get(i + 1).getId());
}
}
else if (fromPosition > toPosition) { // jeśli notka idzie w lewo albo w górę
db.updateOrder(notesList.get(toPosition).getNoteOrder(), notesList.get(fromPosition).getId());
for (int i = fromPosition; i >= toPosition + 1; i--) {
db.updateOrder(notesList.get(i).getNoteOrder(), notesList.get(i - 1).getId());
}
}
Collections.swap(notesList, fromPosition, toPosition);
/* HERE IS THE PROBLEM */
Objects.requireNonNull(recyclerView.getAdapter()).notifyItemMoved(fromPosition, toPosition);
return true;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
}
@Override
public int getSwipeDirs(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
return 0;
}
@Override
public void onSelectedChanged(@Nullable RecyclerView.ViewHolder viewHolder, int actionState) {
super.onSelectedChanged(viewHolder, actionState);
if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) {
Objects.requireNonNull(viewHolder).itemView.setAlpha(0.5f);
}
}
@Override
public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
viewHolder.itemView.setAlpha(1f);
Parcelable recylerViewState = Objects.requireNonNull(recyclerView.getLayoutManager()).onSaveInstanceState();
notesList = db.getAllNotes();
configureRecyclerView(view, notesList);
recyclerView.getLayoutManager().onRestoreInstanceState(recylerViewState);
}
};
new ItemTouchHelper(simpleCallback).attachToRecyclerView(noteRecyclerView);
swipeContainer = view.findViewById(R.id.swipeContainer);
swipeContainer.setOnRefreshListener(() -> {
notesList.clear();
notesList.addAll(db.getAllNotes());
swipeContainer.setRefreshing(false);
});
}
private void configureRecyclerView(View view, List<Note> notes) {
noteRecyclerView = view.findViewById(R.id.recyclerview);
noteRecyclerView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
startPostponedEnterTransition();
noteRecyclerView.getViewTreeObserver().removeOnPreDrawListener(this);
return true;
}
});
noteRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
lastPosition = dy;
}
});
GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(), Integer.parseInt(colsNumber));
noteRecyclerView.setLayoutManager(gridLayoutManager);
NoteAdapter noteDataAdapter = new NoteAdapter(notes, getContext(), (ActivityMain) getActivity(), bottomNavHeight, Integer.parseInt(colsNumber), this);
noteRecyclerView.setAdapter(noteDataAdapter);
if(sp.getInt("scroll_main", 0) != 0) {
noteRecyclerView.post(new Runnable() {
@Override
public void run() {
noteRecyclerView.scrollBy(0, sp.getInt("scroll_main", 0));
}
});
}
}
Any help will be appreciated.
EDIT but maybe the problem can be in clearView
() I don't know
Thank you in advance!
I found a solution. Simply I removed overrided getItemViewType()
from my recyclerview adapter.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.