在阅读一些文章之后,我尝试使用以下内容创建一个android应用程序:
recyclerview
,它使用实时数据从会议室数据库中获取数据。recyclerview中的功能:
引荐文章:
我的问题:
房间资料库中的数据重新排序不会更新。
注意:
我正在使用属性进行数据排序
如果您需要实现的更多详细信息,请参考this GitHub repository。我为此问题创建了一个示例应用。
(添加有问题的完整代码似乎太长了,请参考我的github存储库以获取代码)
如果需要特定文件的代码,请发表评论。我不确定要发布哪个代码。
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);
}
MainActivityViewModel.java
public void moveWord(int fromPosition, int toPosition) {
// Move word
wordRepository.move(fromPosition, toPosition);
}
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;
}
}
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);
答案 0 :(得分:1)
这是一种简单的订购商品的方法,与Room数据库一起使用。
实体对象(模型):
订单列,输入Integer:
@ColumnInfo(name = "word_order")
private Integer mOrder;
在道:
查询,该查询检索列word_order
中的最大订单:
@Query("SELECT MAX(word_order) FROM word_table")
int getLargestOrder();
以及更新整个单词列表的查询:
@Update(onConflict = OnConflictStrategy.REPLACE)
void update(List<WordEntity> wordEntities);
使用
MAX
SQL命令获取最大数量。
活动中(添加新单词时):
查询该方法getLargestOrder()
并为其添加+1,然后创建一个新单词。
活动中(onCreate()):
创建ItemTouchHelper
来移动单词项,仅使用UP和DOWN移动:
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.UP | ItemTouchHelper.DOWN) {
});
这是一个实用程序类,可添加滑动以关闭并拖放对RecyclerView的支持。 它与RecyclerView和Callback类一起使用,后者可配置启用哪种类型的交互,并在用户执行这些操作时接收事件。
覆盖其中的getMovementFlags
以指定所需的路线:
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
return makeMovementFlags(ItemTouchHelper.UP | ItemTouchHelper.DOWN,
0);
}
覆盖其中的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;
}
此方法可在移动物品时更新其位置。
首先,从适配器获取物品的位置。
然后,如果递减,则通过传递当前项位置和新项位置(供用户查看)来交换实体项。
然后,获得当前商品和下一个商品的订单,并对其进行擦拭并使用setter方法进行设置(以便稍后将其保存在Room中)。
另一方面,对增量进行相同的操作。
完成,通过通知适配器项已移动(供用户查看)。
覆盖clearView
以更新单词实体列表:
@Override
public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
mWordViewModel.update(mWordEntities);
}
当用户放置物品时调用此方法。更新实体并将其保存到会议室数据库将是合适的。
覆盖onSwiped
:
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
}
这必须由系统覆盖。
将ItemTouchHelper
附加到RecyclerView:
itemTouchHelper.attachToRecyclerView(mRecyclerView);
您可以创建许多ItemTouchHelper,并根据需要将它们附加到RecyclerView。
请注意,您需要在RecyclerView中从最大编号到最低编号订购商品。希望对您有帮助:)
答案 1 :(得分:1)
嗨:)我会这样:
我将在您的Word对象中添加一个“位置”列,并使其与您的words.size()相等。这将使其成为“自动增量”,但不一定是唯一的(这很重要)。
因此,当您向数据库中添加新的Word时,您将执行以下操作:
wordsDao.insert(new Word(position, whateverYouNeedToAdd));
用你的话语道:
@Query("SELECT * FROM word ORDER BY position ASC")
LiveData<List<WORD>> sortByPositio();
在ViewModel中:
public WordsViewModel(@NonNull Application application) {
super(application);
wordsDao = getDatabase(application).wordsDao();
wordsLiveData = wordsDao.sortByPosition();
}
public LiveData<List<Word>> getWordsList() {
return wordsLiveData;
}
在活动中显示列表的地方:
public void initData(){
wordsViewModel = ViewModelProviders.of(this).get(WordsViewModel.class);
wordsViewModel.getWordsList().observe(this, new Observer<List<Word>>() {
@Override
public void onChanged(@Nullable List<Word> words) {
adapter.setWordsList(words);
if (words == null) {
position = 0;
} else {
position = words.size();
}
}
});
}
在您的适配器中:
void setWordsList(List<Word> wordsList) {
this.wordsList = wordsList;
notifyDataSetChanged();
}
移动项目:
public void onItemMove(int fromPosition, int toPosition) {
if (fromPosition < toPosition) {
for (int i = fromPosition; i < toPosition; i++) {
Collections.swap(wordsList, i, i + 1);
}
} else {
for (int i = fromPosition; i > toPosition; i--) {
Collections.swap(wordsList, i, i - 1);
}
}
notifyItemMoved(fromPosition, toPosition);
}
我将在适配器中创建一个方法,在其中更新数据库中的位置:
void setIndexInDatabase() {
WordsDao wordsDao = getDatabase(context).wordsDao();
for (Word word : wordsList) {
word.setPosition(wordsList.indexOf(words));
wordsDao.update(word);
}
我会在您在onDestroy
中显示列表的活动中调用该方法:
@Override
public void onDestroy() {
super.onDestroy();
adapter.setIndexInDatabase();
}
因此,现在用户可以根据需要移动物品,当他完成并转到另一个活动时,新订单将保存在数据库中。
首先,我将在您的适配器中创建一个arraylist,以在其中存储已删除项目的列表
private ArrayList<String> deletedWords = new ArrayList<>();
然后我将创建删除和撤消方法:
public void deleteItem(int position) {
word = wordsList.get(position);
wordPosition = position;
deletedWord = word.getWord();
deletedWords.add(deletedWord);
wordsList.remove(position);
notifyItemRemoved(position);
showUndoSnackbar();
}
我要在我们创建的数组中添加一个要删除的单词。
private void showUndoSnackbar() {
Snackbar snackbar = Snackbar.make( (((Activity) context).findViewById(android.R.id.content)), R.string.snack_bar_text,
Snackbar.LENGTH_LONG);
snackbar.setAction(R.string.snack_bar_undo, new View.OnClickListener() {
@Override
public void onClick(View v) {
undoDelete();
}
});
snackbar.show();
}
private void undoDelete() {
wordsList.add(wordPosition,
word);
deletedWords.remove(deletedWord);
notifyItemInserted(wordPosition);
}
在undoDelete
中,我将从我们的arrayList
我将创建一种方法来从数据库中删除arrayList
中存储的所有单词:
void deleteFromDatabase() {
WordsDao wordsDao = getDatabase(context).wordsDao();
if (deletedWords != null) {
for (int i = 0; i < deletedWords.size(); i++) {
wordsDao.deleteByWord(deletedWords.get(i));
}
}
}
我会像以前一样在onDestroy
中称呼它:
@Override
public void onDestroy() {
super.onDestroy();
adapter.setIndexInDatabase();
adapter.deleteFromDatabase();
}
我希望我不会忘记任何事情:)我在正在编写的应用程序中做了类似的事情,因此您也可以在github上进行检查。
我在Shift包中使用它:ShiftFragment
和ShiftAdapter
。