我有一個String
類型的二維ArrayList
,它是RecyclerView
的適配器類別的輸入。列表中的數據每次調用onResume()
時都從SQLite數據庫中獲取。我已經實現了一個拖放功能和一個可以成功交換列表元素的函數onMove()
。但是,我需要在調用onResume()
之前存儲修改後的列表,這將重寫列表並用舊位置填充列表。我的猜測是在onStop()
事件中實現重寫功能。這是我的主要活動:被拖放後在SQLite中存儲RecyclerView項目的新位置
RecyclerView recyclerView;
RecyclerViewAdapter adapter;
RecyclerView.LayoutManager layoutManager;
ArrayList<ArrayList<String>> data;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
assert fab != null;
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent i = new Intent(MainActivity.this, ViewDbActivity.class);
startActivity(i);
}
});
recyclerView = (RecyclerView) findViewById(R.id.myRecyclerView);
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
RecyclerView.ItemAnimator itemAnimator = new DefaultItemAnimator();
ItemTouchHelper item = new ItemTouchHelper(new ItemTouchHelper.Callback() {
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
int swipeFlags = ItemTouchHelper.RIGHT;
return makeMovementFlags(dragFlags, swipeFlags);
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
Collections.swap(data, viewHolder.getAdapterPosition(), target.getAdapterPosition());
adapter.notifyItemMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
@Override
public void onMoved(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, int fromPos, RecyclerView.ViewHolder target, int toPos, int x, int y) {
super.onMoved(recyclerView, viewHolder, fromPos, target, toPos, x, y);
Toast.makeText(MainActivity.this, "Moved", Toast.LENGTH_SHORT).show();
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
data.remove(viewHolder.getAdapterPosition());
adapter.notifyItemRemoved(viewHolder.getAdapterPosition());
}
});
item.attachToRecyclerView(recyclerView);
recyclerView.setItemAnimator(itemAnimator);
}
@Override
protected void onResume() {
super.onResume();
initialize();
if(adapter == null) {
Log.v(TAG, "Adapter = NULL. Initialized");
setAdapter();
}
else {
Log.v(TAG, "notify is called");
adapter.updateData(data);
}
}
public void initialize() {
Database ourDB = new Database(this);
ourDB.openDB();
data = ourDB.getData();
ourDB.closeDB();
}
public void setAdapter() {
adapter = new RecyclerViewAdapter(data, this);
recyclerView.setAdapter(adapter);
}
只要知道何時存儲數據,更新數據庫非常重要。我怎麼解決這個問題?有什麼建議麼?
!!!
答:
最終的解決方案我已經實現:
@Override
public void onMoved(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, int fromPos, RecyclerView.ViewHolder target, int toPos, int x, int y) {
super.onMoved(recyclerView, viewHolder, fromPos, target, toPos, x, y);
//preparing new position values
long movedItem = Long.parseLong(data.get(fromPos).get(0)); // .get(fromPos).get(0) returns PRIMARY KEY from the list
long draggedItem = Long.parseLong(data.get(toPos).get(0));
// updating affected rows with new orders
Database db = new Database(MainActivity.this);
db.open();
db.updateOrder(draggedItem, toPos);
db.updateOrder(movedItem, fromPos);
db.close();
}
和DB類的內部:
public void updateOrder(long rowID, int newPos) {
ContentValues cv = new ContentValues();
cv.put(KEY_ORDER, newPos);
ourDatabase.update(DATABASE_TABLE, cv, KEY_ROWID + "=" + rowID, null);
}
感謝您的回答。這是我的錯,我忘了提及我有一個單獨的專欄用於存儲訂單,正如您所說的,當我創建新項目時,我會增加最大行數。我有和你提供的相同的想法,但我擔心應用程序的性能。因爲每次交換列表項時都會調用onMoved。如果用戶非常快地拖動項目,可能會導致應用程序被凍結。你對此有何看法? – Marat
所以你只需要實現列表的第二個點。你可以在數據庫類中添加方法(例如'moveOrderUp(int from,int to)'和'moveOrderDown(int from,int to)',或者直接在你的'onMoved'方法中進行。對我來說,第一種方法是更好 – rsella
我的第二個想法是使用已經存儲新鮮數據的ArrayList <>,正如你可以看到'onMove'將那些被移動的項目交換到那裏,現在我想我可以嘗試從數據庫中刪除所有數據,排序列表對象並重新上傳到數據庫,但我不知道在哪裏實現它,以及它會如何影響性能,但現在你的解決方案只需重寫數據庫中的受影響的行,並在開始時對其進行排序 – Marat