简体   繁体   中英

Android recyclerview adapter notifyItemMoved crashes

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.

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