将回收者视图数据中的 onMove() 更改更新到房间数据库

Abh*_*bhi 8 android drag-and-drop android-recyclerview android-room

根据一些文章,我正在尝试使用以下内容创建一个 android 应用程序:

  • recyclerview使用实时数据从房间数据库中获取数据的A。
  • 数据结构是一个自定义对象列表,具有用于对数据进行排序的属性。

recyclerview 中的功能:

  • 拖放以重新排序数据
  • 滑动删除
  • 用于滑动删除的撤消操作

参考文章:

  1. 用于房间数据库和实时数据的 Google 代码实验室
  2. AndroidHive 文章 recyclerview 滑动删除和撤消恢复已删除的项目
  3. Paul Burke 的中篇文章,用于在回收站视图中拖放
  4. Paul Burke 的中篇文章,用于在回收站视图中自定义拖动的项目
  5. SO Post 以检测回收站视图中的丢弃事件

我的问题:
房间库中的数据重新排序未更新。

注意:
我使用属性进行数据排序

如果需要特定文件的代码,请发表评论。我不确定要发布哪个代码。

MainFragment.java (重新排序数据的代码,不起作用)

// To handle recycler view item dragging
@Override
public void onItemMove(int fromPosition, int toPosition) {

    // Log
    Log.e(TAG, "Item moved from " + fromPosition + " to " + toPosition);

    // Move the item within the recycler view
    mainRecyclerViewAdapter.moveItem(fromPosition, toPosition);
}

// To handle recycler view item drop
@Override
public void onItemDragged(int fromPosition, int toPosition) {

    // Log
    Log.e(TAG, "Item dragged from " + fromPosition + " to " + toPosition);

    mainActivityViewModel.moveWord(fromPosition, toPosition);
}
Run Code Online (Sandbox Code Playgroud)

主ActivityViewModel.java

public void moveWord(int fromPosition, int toPosition) {

    // Move word
    wordRepository.move(fromPosition, toPosition);
}
Run Code Online (Sandbox Code Playgroud)

WordRepository.java

public void move(int from, int to) {
    new moveAsyncTask(wordDao).execute(from, to);
}

// Async update task
private static class moveAsyncTask extends AsyncTask<Integer, Void, Void> {


    // Dao
    private WordDao asyncTaskDao;


    // Constructor
    moveAsyncTask(WordDao wordDao) {

        // Get dao
        asyncTaskDao = wordDao;
    }


    @Override
    protected Void doInBackground(final Integer... params) {

        int from = params[0];
        int to = params[1];

        if (from > to) {

            // Move upwards

            asyncTaskDao.getAllWordsBetween(to, from - 1).forEach(wordToUpdate -> {

                // Update word number
                wordToUpdate.decreaseSNo();

                // Update word in database
                update(wordToUpdate);
            });

            asyncTaskDao.getWordWithNo(from).forEach(wordToUpdate -> {

                // Update word number
                wordToUpdate.setSno(to);

                // Update word in database
                update(wordToUpdate);
            });

        } else {

            // Move downwards

            asyncTaskDao.getAllWordsBetween(from + 1, to).forEach(wordToUpdate -> {

                // Update word number
                wordToUpdate.increaseSNo();

                // Update word in database
                update(wordToUpdate);
            });

            asyncTaskDao.getWordWithNo(from).forEach(wordToUpdate -> {

                // Update word number
                wordToUpdate.setSno(to);

                // Update word in database
                update(wordToUpdate);
            });

        }

        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

WordDao.java

@Query("SELECT * FROM words WHERE sno >= :low AND sno <= :high")
List<Word> getAllWordsBetween(int low, int high);

@Query("SELECT * FROM words WHERE sno == :sNo")
List<Word> getWordWithNo(int sNo);
Run Code Online (Sandbox Code Playgroud)

Moh*_*adL 8

这是订购物品的简单方法,将它与房间数据库一起使用。

实体对象(模型):

订单列,输入整数:

@ColumnInfo(name = "word_order")
private Integer mOrder;
Run Code Online (Sandbox Code Playgroud)

在道:

检索列中最大顺序的查询word_order

@Query("SELECT MAX(word_order) FROM word_table")
int getLargestOrder();
Run Code Online (Sandbox Code Playgroud)

以及更新整个单词列表的查询:

@Update(onConflict = OnConflictStrategy.REPLACE)
void update(List<WordEntity> wordEntities);
Run Code Online (Sandbox Code Playgroud)

使用MAXSQL 命令获取最大数。

在活动中(添加新词时):

查询该方法getLargestOrder()并为其添加 +1,然后创建一个新单词。

在活动中(onCreate()):

创建ItemTouchHelper移动单词项,仅使用 UP 和 DOWN 移动:

ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.UP | ItemTouchHelper.DOWN) {

});
Run Code Online (Sandbox Code Playgroud)

这是一个实用程序类,用于向 RecyclerView 添加滑动以关闭和拖放支持。它与 RecyclerView 和 Callback 类一起工作,该类配置启用的交互类型,并在用户执行这些操作时接收事件。

覆盖getMovementFlags其中以指定所需的方向:

        @Override
        public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
            return makeMovementFlags(ItemTouchHelper.UP | ItemTouchHelper.DOWN,
                    0);
        }
Run Code Online (Sandbox Code Playgroud)

onMove在其中覆盖以交换项目位置:

        @Override
        public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
            int fromPosition = viewHolder.getAdapterPosition();
            int toPosition = target.getAdapterPosition();

            if (fromPosition < toPosition) {
                for (int i = fromPosition; i < toPosition; i++) {
                    Collections.swap(mWordEntities, i, i + 1);

                    int order1 = mWordEntities.get(i).getOrder();
                    int order2 = mWordEntities.get(i + 1).getOrder();
                    mWordEntities.get(i).setOrder(order2);
                    mWordEntities.get(i + 1).setOrder(order1);
                }
            } else {
                for (int i = fromPosition; i > toPosition; i--) {
                    Collections.swap(mWordEntities, i, i - 1);

                    int order1 = mWordEntities.get(i).getOrder();
                    int order2 = mWordEntities.get(i - 1).getOrder();
                    mWordEntities.get(i).setOrder(order2);
                    mWordEntities.get(i - 1).setOrder(order1);
                }
            }
            mAdapter.notifyItemMoved(fromPosition, toPosition);
            return true;
        }
Run Code Online (Sandbox Code Playgroud)

此方法在移动时更新项目位置。

  • 首先,从适配器获取项目的位置。

  • 然后,如果递减,则通过传递当前项目位置和新位置(对于用户眼睛)来交换实体的项目。

  • 之后,获取当前项目和下一个项目的顺序,并擦拭它们并使用 setter 方法设置它们(以便稍后将它们保存在 Room 中)。

  • 另一方面,对增量做同样的事情。

  • 完成后,通过通知适配器项目已经移动(对于用户眼睛)。

覆盖clearView以更新 Word 实体列表:

        @Override
        public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
            super.clearView(recyclerView, viewHolder);
            mWordViewModel.update(mWordEntities);
        }
Run Code Online (Sandbox Code Playgroud)

当用户放下项目时调用此方法。将适合更新实体并将其保存到房间数据库中。

覆盖onSwiped

        @Override
        public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
        }
Run Code Online (Sandbox Code Playgroud)

这必须由系统覆盖。

附加ItemTouchHelper到 RecyclerView:

itemTouchHelper.attachToRecyclerView(mRecyclerView);
Run Code Online (Sandbox Code Playgroud)

您可以根据需要创建许多 ItemTouchHelper 并将它们附加到 RecyclerView。

请注意,您需要将 RecyclerView 中的项目从最大数到最小数排序。希望这对你有帮助:)