拖放后在 SQLite 中存储 RecyclerView 项目的新位置 [英] Store new position of RecyclerView items in SQLite after being dragged and dropped

查看:34
本文介绍了拖放后在 SQLite 中存储 RecyclerView 项目的新位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a two dimensional ArrayList of type String which is the input to the adapter class of the RecyclerView. The data in the list is taken from an SQLite database everytime when onResume() is called. I have implemented a drag and drop feature and an onMove() function that swaps the list elements successfully. However, I need to store the modified list before onResume() is called which will rewrite the list and fill it with old positions. My guess is to implement the rewriting functionality within the onStop() event. This is my main activity:

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

只要我知道何时存储数据,更新数据库就很重要.我怎么解决这个问题?有什么建议吗?

It is important to update the database as long as I know when to store the data. How can I solve this problem? Any suggestions?

!!!

回答:

我实施的最终解决方案:

Final solution I have implemented:

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

推荐答案

您需要在每个 DB 行中都有一个字段来存储订单.然后你需要实现这些功能:

You need a field in each DB row for storing the order. Then you need to implements those features:

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

  • On new row insert (when you insert a new object in database) you need to set the order field to the next int. You can get the current max value (with sql function MAX) and then simply do +1

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

When user move an item in RecyclerView, in method onMovedyou must update all other rows. You can use the fromPos and toPos for that. More on that below

当您用数据填充 RecyclerView 时,您需要按 order 字段对它们进行排序

When you fill your RecyclerView with data you need to order them by order field


要实现的第二个功能的说明:基本上你需要用 fromPostoPos 之间的顺序更新所有行:


Explanation of 2nd feature to be implemented: basically you need to update all rows with order between fromPos and toPos:

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

  • if user moved the item up (for example from position 4 to 2), you need to:

  1. 获取当前项目的主键字段(使用位置 4)
  2. 更改顺序 2 和顺序 4 之间的所有行:因此更改 2 -> 3 和 3 -> 4
  3. 将当前项目顺序(使用第一点的主键)更改为 toPos:在此示例中将当前项目顺序更改为 2
  1. get primary key field of current item (using position 4)
  2. change all rows between order 2 and order 4: so change 2 -> 3 and 3 -> 4
  3. Change current item order (using primary key of first point) to toPos: in this example change current item order to 2

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

  • if user moved the item down (for example from position 2 to 4) you need to:

    1. 获取当前项目的主键字段(使用位置 2)
    2. 在 order 2 和 order 4 之间更改所有行:因此更改 4 -> 3 和 3 -> 2
    3. 将当前项目顺序(使用第一个点的主键)更改为 toPos:在此示例中,将当前项目顺序更改为 4
    1. get primary key field of current item (using position 2)
    2. change all rows between order 2 and order 4: so change 4 -> 3 and 3 -> 2
    3. change current item order (using primary key of first point) to toPos: in this example change current item order to 4


  • 希望对你有帮助


    Hope it helps a little

    这篇关于拖放后在 SQLite 中存储 RecyclerView 项目的新位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆