3

我有一個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); 
} 

回答

4

你需要在每個DB行中的一個字段,存儲的順序。 然後,你需要實現這些功能:

  • 新行插入(當您插入在數據庫中的新對象),您需要將爲了字段設置爲下一個int值。您可以獲得當前最大值(與SQL函數MAX),然後簡單地做+1

  • 當用戶在RecyclerView移動項目,在方法onMoved必須更新所有其他行。您可以使用fromPostoPos。更多關於這下面

  • 當你填寫你RecyclerView數據,你需要通過order現場責令其



第二功能的說明,以實現: 基本上你需要更新訂單在fromPostoPos之間的所有行:

  • 如果用戶移動的項目向上(例如,從位置4到2),則需要:

    1. 獲得當前項目的主鍵字段(使用位置4)
    2. 變化的所有行順序之間2和順序:如此改變2 - > 3,3 - > 4
    3. 更改當前項順序(使用第一點的主鍵)toPos:在這個例子中當前項順序更改爲2
  • 如果用戶移動的項目下(例如,從位置2〜4),你需要:

    1. 獲得當前項目的主鍵字段(使用位置2)
    2. 變更單2之間的所有行訂購4:SO 4改變 - > 3和3 - > 2
    3. 改變當前項順序(使用第一點的主鍵)toPos:在本例中改變當前項以4


希望它有一點幫助

+0

感謝您的回答。這是我的錯,我忘了提及我有一個單獨的專欄用於存儲訂單,正如您所說的,當我創建新項目時,我會增加最大行數。我有和你提供的相同的想法,但我擔心應用程序的性能。因爲每次交換列表項時都會調用onMoved。如果用戶非常快地拖動項目,可能會導致應用程序被凍結。你對此有何看法? – Marat

+0

所以你只需要實現列表的第二個點。你可以在數據庫類中添加方法(例如'moveOrderUp(int from,int to)'和'moveOrderDown(int from,int to)',或者直接在你的'onMoved'方法中進行。對我來說,第一種方法是更好 – rsella

+0

我的第二個想法是使用已經存儲新鮮數據的ArrayList <>,正如你可以看到'onMove'將那些被移動的項目交換到那裏,現在我想我可以嘗試從數據庫中刪除所有數據,排序列表對象並重新上傳到數據庫,但我不知道在哪裏實現它,以及它會如何影響性能,但現在你的解決方案只需重寫數據庫中的受影響的行,並在開始時對其進行排序 – Marat

相關問題