拖放后,将RecyclerView项目的新位置存储在SQLite中

时间:2016-07-06 11:38:26

标签: android drag-and-drop android-recyclerview android-sqlite

我有ArrayList类型的String,它是RecyclerView的适配器类的输入。每次调用onResume()时,列表中的数据都来自SQLite数据库。我已经实现了拖放功能和onMove()功能,可以成功交换列表元素。但是,我需要在调用onResume()之前存储修改后的列表,这将重写列表并用旧位置填充它。我的猜测是在onStop()事件中实现重写功能。这是我的主要活动:

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);
}

1 个答案:

答案 0 :(得分:5)

每个数据库行中都需要一个字段来存储订单。 然后,您需要实现这些功能:

  • 在新行插入时(在数据库中插入新对象时),需要将 order 字段设置为下一个int。您可以获取当前最大值(使用sql函数MAX),然后只需执行+1

  • 当用户在RecyclerView中移动项目时,在方法onMoved中,您必须更新所有其他行。您可以使用fromPostoPos。更多关于以下内容

  • 当您在RecyclerView填充数据时,需要按order字段

  • 进行排序


要实施的第二个特征的说明: 基本上,您需要使用fromPostoPos之间的顺序更新所有行:

  • 如果用户向上移动项目(例如从位置4移动到2),您需要:

    1. 获取当前项目的主键字段(使用位置4)
    2. 更改订单 2 和订单 4 之间的所有行:因此请更改2 - &gt; 3和3 - &gt; 4
    3. 将当前项目顺序(使用第一个点的主键)更改为toPos:在此示例中,将当前项目顺序更改为2
  • 如果用户将项目向下移动(例如从位置2移动到4),则需要:

    1. 获取当前项目的主键字段(使用位置2)
    2. 更改订单2和订单4之间的所有行:因此更改4 - &gt; 3和3 - &gt; 2
    3. 将当前项目顺序(使用第一个点的主键)更改为toPos:在此示例中,将当前项目顺序更改为4


希望它有所帮助