Сортировка элементов RecyclerView с помощью базы данных

avatar
Yogev Uzan
8 апреля 2018 в 09:51
866
2
2

Сейчас я работаю над музыкальным приложением, в котором есть вкладка "Избранные песни". Я пытаюсь реализовать инструмент, который позволит пользователям сортировать свои любимые песни, хранящиеся в БАЗЕ ДАННЫХ, с помощью перетаскивания.

В этом случае я использую ItemTouchHelper, но ни один из моих поисков не дал решения, которое работает с базой данных.

** Мой список заполняется из базы данных **

ИзбранноеPresenter.class

        ItemTouchHelper.SimpleCallback simpleCallback =
                new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN, 0) {

                    @Override
                    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
                        mRecyclerView.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);

                    }

DataBase.class

int updateOrder(long id, int newPos) {
    ContentValues cv = new ContentValues();
    cv.put(DataBaseOpenHelper.COLUMN_ORDER, newPos);

    String where = DataBaseOpenHelper.COLUMN_ID + "=?";
    String[] whereArgs = {String.valueOf(id)};

    return getWritable().update(DataBaseOpenHelper.TABLE_NAME_FAVORITE, cv, where, whereArgs);
}

Я пробовал это "решение" здесь, но, очевидно, оно мне не подходит. Есть предложения?

Источник

Ответы (2)

avatar
SammyT
6 сентября 2018 в 04:50
0

Используя этот туториал (упомянутый Fazel): https://medium.com/@ipaulpro/drag-and-swipe-with-recyclerview-6a6f0c422efd

Я создал решение, которое мне подходит. Я не знаю, правильно ли это, и, возможно, кто-то сможет улучшить этот ответ.

onItemMove() и onMoved() вызываются, пока я все еще перетаскивал элемент. clearView() вызывается только один раз. Поскольку я использую Firestore в качестве базы данных, я действительно хочу обновлять элементы только после завершения перетаскивания.

Я обновляю категории, поэтому у меня есть CategoryFirestoreAdapter, который расширяет FirestoreAdapter. Мой порядок сортировки, сохраненный в базе данных, начинается с 1 (не 0).

ItemTouchHelperAdapter

public interface ItemTouchHelperAdapter {

    boolean onItemMove(int fromPosition, int toPosition);

    void onItemDismiss(int position);

    void clearView(); //added this
}

SimpleItemTouchHelperCallback

@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {

    super.clearView(recyclerView, viewHolder);

    viewHolder.itemView.setAlpha(ALPHA_FULL);

    if (viewHolder instanceof ItemTouchHelperViewHolder) {
        // Tell the view holder it's time to restore the idle state
        ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder;
        itemViewHolder.onItemClear();
    }
    mAdapter.clearView(); //add this so the method gets called in the CategoryFirestoreAdapter
}

КатегорияFirestoreAdapter

public class CategoryFirestoreAdapter
    extends FirestoreAdapter<CategoryFirestoreAdapter.ViewHolder>
    implements ItemTouchHelperAdapter {

@Override
public void clearView() {

    //Update the database here for the items that have moved.

    FirebaseFirestore db = FirebaseFirestore.getInstance();
    ArrayList<DocumentSnapshot> snapshots = getAllItems();

    db.runTransaction(new Transaction.Function<Object>() {

        @Nullable
        @Override
        public Object apply(@NonNull Transaction transaction) {

            for (int i = 0; i < snapshots.size(); i++) {

                DocumentSnapshot snapshot = snapshots.get(i);
                DocumentReference docRef = db.collection("categories").document(snapshot.getId());
                Category category = snapshot.toObject(Category.class);

                Integer sortOrder = category.getSortOrder();
                Integer newSortOrder = i+1;

                if ((i + 1) != sortOrder) {
                    //only update items that have changed.
                    transaction.update(docRef, "sortOrder", newSortOrder); //sortOrder hardcoded - fix this
                }
            }
            return null;
        }
    });
} ....

FirestoreAdapter

protected void onDocumentModified(DocumentChange change) {

//    I changed this as it was moving things around again after updating the db.  
//    I am not sure why, and this may need improving, but this is working for me.

//    Dont handle position changes, just updates.
//    if (change.getOldIndex() == change.getNewIndex()) {
//        // Item changed but remained in same position
//        mSnapshots.set(change.getOldIndex(), change.getDocument());
//        notifyItemChanged(change.getOldIndex());
//    } else {
//        // Item changed and changed position
        mSnapshots.remove(change.getOldIndex());
        mSnapshots.add(change.getNewIndex(), change.getDocument());
//        notifyItemMoved(change.getOldIndex(), change.getNewIndex());
        notifyItemChanged(change.getNewIndex()); //added
        notifyItemChanged(change.getOldIndex()); //added
//    }
}

protected ArrayList<DocumentSnapshot> getAllItems() {
    return mSnapshots;
}
avatar
Fazal Hussain
8 апреля 2018 в 10:10
0

Сортировка перетаскиванием с помощью Android recyclerview проста и не требует использования сторонних библиотек

private final OnStartDragListener mDragStartListener;

public RecyclerListAdapter(OnStartDragListener dragStartListener) {
mDragStartListener = dragStartListener;
// ...
}@Override
public void onBindViewHolder(final ItemViewHolder holder, 
int position) {
// ... holder.handleView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (MotionEventCompat.getActionMasked(event) == 
MotionEvent.ACTION_DOWN) {
mDragStartListener.onStartDrag(holder);
}
return false;
}
});
}

Для получения дополнительной информации см. пост ниже

https://medium.com/@ipaulpro/drag-and-swipe-with-recyclerview-6a6f0c422efd

Yogev Uzan
8 апреля 2018 в 11:40
0

Думаю, я недостаточно ясно выразился... Я пытаюсь дать пользователю возможность сортировать свои любимые песни путем перетаскивания, а затем сохранять текущий список в базе данных...

Yogev Uzan
9 апреля 2018 в 04:34
0

Сортировка списка работает отлично. Просто он не будет сохранен в БАЗЕ ДАННЫХ, что означает, что после сортировки списка и воспроизведения песни воспроизводится предыдущая песня.

Fazal Hussain
9 апреля 2018 в 06:33
0

Удалить все данные из таблицы сохранить данные с новым отсортированным списком в таблице