Сохранение новой позиции элементов RecyclerView в SQLite после перетаскивания

У меня двухмерныйArrayList типаString который является входом в класс адаптераRecyclerView, Данные в списке берутся из базы данных SQLite каждый раз, когдаonResume() называется. Я реализовал функцию перетаскивания и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();
}

И внутри класса БД:

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)

Решение Вопроса

Вам нужно поле в каждой строке БД для хранения заказа. Затем вам нужно реализовать эти функции:

При вставке новой строки (при вставке нового объекта в базу данных) необходимо установитьпорядок поле к следующему инт. Вы можете получить текущее максимальное значение (с помощью функции sqlMAX) а потом просто делай +1

Когда пользователь перемещает элемент вRecyclerViewв методеonMovedВы должны обновить все остальные строки. Вы можете использоватьfromPos а такжеtoPos для этого. Подробнее об этом ниже

Когда вы заполняете свойRecyclerView с данными вам нужно заказать их поorder поле


Объяснение 2-й функции, которая будет реализована: в основном вам нужно обновить все строки в порядке междуfromPos а такжеtoPos:

если пользователь переместил элемент вверх (например, с позиции 4 на 2), вам необходимо:

получить поле первичного ключа текущего элемента (используя позицию 4)изменить все строки между порядком2 и заказать4: так измените 2 -> 3 и 3 -> 4Изменить текущий порядок позиций (используя первичный ключ первой точки) наtoPos: в этом примере изменить текущий порядок элементов на 2

если пользователь переместил элемент вниз (например, с позиции 2 на 4), вам необходимо:

получить поле первичного ключа текущего элемента (используя позицию 2)измените все строки между порядком 2 и порядком 4: измените 4 -> 3 и 3 -> 2изменить текущий порядок элементов (используя первичный ключ первой точки) наtoPos: в этом примере изменить текущий порядок позиций на 4


Надеюсь, это немного поможет

 Spritzig24 февр. 2019 г., 22:04
@ rsella Я пытаюсь сделать то же самое, изменив позицию реселлера с помощью onItemMoved, но при этомSQLite
 rsella06 июл. 2016 г., 16:06
Так что вам просто нужно реализовать 2-й пункт списка. Вы можете добавить методы в класс базы данных (например,moveOrderUp(int from, int to) а такжеmoveOrderDown(int from, int to) или сделать это прямо в вашемonMoved метод. Для меня первый подход лучше
 rsella06 июл. 2016 г., 16:37
Теперь я понимаю, извините за это. Вы можете получить текущий перетаскиваемый элемент вonMoved метод. Просто найдите его в arraylist, используяfromPos параметр (соответствует текущему порядку элементов в ArrayList)
 Marat06 июл. 2016 г., 16:57
Спасибо! Я скоро попробую эту идею
 Marat06 июл. 2016 г., 16:13
Моя вторая идея состояла в том, чтобы использовать ArrayList <>, который уже хранит свежие данные. Как вы видетеonMove меняет местами перемещенные предметы Теперь я подумал, что, возможно, я мог бы попытаться удалить все данные из БД, отсортировать объект списка и снова загрузить его в БД. Но я не знаю, где это реализовать и как это повлияет на производительность. Но пока ваше решение просто переписать затронутые строки в БД и отсортировать их при запуске
 Marat06 июл. 2016 г., 16:28
Хорошо, тогда. Но как получить строку, которая соответствует перетаскиваемому элементу?
 Spritzig14 февр. 2019 г., 11:03
@ Марат Вы получили ответ, потому что я пытаюсь сделать то же самое, что мне нужно, чтобы сохранить новую позицию наSQLite, Если вы сделали это, вы можете поделиться кодом.
 Marat06 июл. 2016 г., 16:03
Спасибо за Ваш ответ. Я забыл упомянуть, что у меня есть отдельный столбец для хранения заказа, и, как вы сказали, когда я создаю новый элемент, я увеличиваю максимальную строку. У меня была та же идея, что и вы, но я беспокоюсь о производительности приложения. Так какonMoved вызывается каждый раз, когда элементы списка меняются местами. Если пользователь перетаскивает элементы очень быстро, это может привести к зависанию приложения. Что ты об этом думаешь?
 rsella06 июл. 2016 г., 16:17
Что ж, удаление и повторная вставка всех данных в базу данных при каждом перемещении строки - это (действительно) плохая идея. С моей идеей вы обновляете только те строки, которые действительно должны быть обновлены. Я не знаю, как использовать эту идею с вашим ArrayList
 Marat06 июл. 2016 г., 16:18
Извините, но я намеревался выполнить эти операции после того, как все перемещения элемента сделаны. Например, вonStop :) Извините за недопонимание.

Ваш ответ на вопрос