Search code examples
javaandroidandroid-recyclerviewdrag-and-dropandroid-room

Saving changes made after Drag 'n' Drop in RecyclerView in Android - I've read everything


I have a RecyclerView with Drag/Drop Capabilities. Drop/Drop is done in Custom Adapter. Using Room for Database, and Entities will not save in "dropped" order.

I have tried about a dozen different methods/githubs:

...and the list goes on...

I've cobbled together code from a bunch of different sources:

My Custom Adapter:

public class SwipeAdapt extends OmegaRecyclerView.Adapter<SwipeAdapt.ViewHolder> {

    public void onItemDismiss(int position) {
        accountList.remove(position);
        notifyItemRemoved(position);
    }
    public boolean onItemMove(int fromPosition, int toPosition) {
        if (fromPosition < toPosition) {
            for (int i = fromPosition; i < toPosition; i++) {
                Collections.swap(accountList, i, i + 1);
            }
        } else {
            for (int i = fromPosition; i > toPosition; i--) {
                Collections.swap(accountList, i, i - 1);
            }
        }

        notifyItemMoved(fromPosition, toPosition);

        return true;
    }

    public void onItemClear() {
        for (int count = 0; count < accountList.size(); count++) {
            Account u = accountList.get(count);
            u.setId(count);
            upAccount(u);
        }
        notifyDataSetChanged();
    }

My Main Activity (Java):

    OmegaRecyclerView RVMain;
    Account crossOver;

    private ItemTouchHelper itemTouchHelper;


        RVMain = (OmegaRecyclerView) findViewById(R.id.theRV);
        RVMain.setLayoutManager(new LinearLayoutManager(this));
        getAccounts();
    }

    private void getAccounts() {
        class GetAccounts extends AsyncTask<Void,Void,List<Account>> {

            @Override
            protected List<Account> doInBackground(Void... voids) {
                List<Account> aList = DataClient.getInstance(getApplicationContext()).getAppDB().theDao().getAll();
                return aList;
            }

            @Override
            protected void onPostExecute(List<Account> accounts) {
                super.onPostExecute(accounts);
                SwipeAdapt adapter = new SwipeAdapt(MainActivity.this, accounts);
                RVMain.setAdapter(adapter);
                DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(RVMain.getContext(), new LinearLayoutManager(getApplicationContext()).getOrientation());
                RVMain.addItemDecoration(dividerItemDecoration);
                ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(adapter);
                itemTouchHelper = new ItemTouchHelper(callback);
                itemTouchHelper.attachToRecyclerView(RVMain);
            }
        }

        GetAccounts ga = new GetAccounts();
        ga.execute();
    }
}

Callback for Drag/Drop

public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback {
    private final SwipeAdapt mAdapter;

    @Override
    public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
        int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
        //int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
        return makeMovementFlags(dragFlags, 0);
    }

    @Override
    public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
        mAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
        return true;
    }

    @Override
    public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
        if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
            if (viewHolder instanceof ItemTouchHelperViewHolder) {
                ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder;
                itemViewHolder.onItemSelected();
            }
        }

        super.onSelectedChanged(viewHolder, actionState);
    }
    @Override
    public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        super.clearView(recyclerView, viewHolder);
            mAdapter.onItemClear();
    }
}

Hopefully, that wasn't too much. I can put the whole thing up on GitHub, if anyone wants. I don't get any errors. Everything looks fine. According to all those sources, I'm doing it correctly. I'm 'notify'ing everything, and such. Yet, every time the activity changes, the RecyclerView order is back to what it was before the Drag/Drop. Any help is greatly appreciated. TIA!


Solution

  • In the bottom of method onItemMove update all data on database with new position.