gpt4 book ai didi

java - 垂直拖放到 RecyclerView 上后如何保留 firestore 中的项目位置

转载 作者:行者123 更新时间:2023-12-02 03:16:06 25 4
gpt4 key购买 nike

在垂直拖放待办事项项目后,我尝试保留待办事项列表应用程序项目的位置。我使用 RecyclerView/FirestoreRecylerAdapter/ItemTouchHelper/Firestore。在 ItemTouchHelper.Callback 的 onMove() 方法中,我猜想是通过异步调用访问 Firestore。这会导致我的 RecyclerView 中发生不需要的内容更改。想象一下,我有一个包含 4 个标题为 A、B、C、D 的项目的列表。现在我将标题为 A 的项目从位置 0(顶部)拖动到位置 1。就像这个项目 B 的标题也更改为 A。但是这个仅在 UI 上,不在 DB 中。当我更改为另一项 Activity 并返回时,标题再次正确。我想这与异步调用有关。

//part of MainActivity onCreate()
mFirestore = FirebaseFirestore.getInstance();
FirebaseFirestore.setLoggingEnabled(true);

FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder()
.setPersistenceEnabled(true)
.build();
mFirestore.setFirestoreSettings(settings);

mRecyclerView = findViewById(R.id.recycler_view);
mUser = FirebaseAuth.getInstance().getCurrentUser();
if(mUser == null){
startSignIn();
}else{
Query mQuery = mFirestore.collection("todos").whereEqualTo("author", mUser.getUid()).whereEqualTo("done", false).orderBy("position", Query.Direction.ASCENDING);

FirestoreRecyclerOptions<Todo> options = new FirestoreRecyclerOptions.Builder<Todo>()
.setQuery(mQuery, Todo.class)
.build();
mAdapter = new TodoAdapter(options);

initRecyclerView();

//ItemTouchHelper.Callback method as part of initRecyclerView()
@Override
public boolean onMove(final RecyclerView recyclerView, final RecyclerView.ViewHolder source, final RecyclerView.ViewHolder target) {
if (source.getItemViewType() != target.getItemViewType()) {
return false;
}

int fromPos = source.getAdapterPosition();
int toPos = target.getAdapterPosition();

//Change items position when an item was draged & droped vertically downwards
if(toPos > fromPos) {
DocumentReference docTo = mAdapter.getSnapshots().getSnapshot(fromPos).getReference();
docTo.update("position", toPos);
int current = fromPos+1;
while(current <= toPos){
DocumentReference docCurrent = mAdapter.getSnapshots().getSnapshot(current).getReference();
docCurrent.update("position", current-1);
current ++;
}

//Change items position when an item was draged & droped vertically upwards
}else if (toPos < fromPos){
//TODO implement
} else {
return false;
}

mAdapter.notifyItemMoved(fromPos, toPos);

return true;
}

//adapter class
public class TodoAdapter extends FirestoreRecyclerAdapter<Todo, TodoAdapter.TodoHolder> {

private static final String TAG = "DOIT_DEBUG: ";

private OnItemClickListener listener;
private View viewItem;

public TodoAdapter(@NonNull FirestoreRecyclerOptions<Todo> options) {
super(options);
}

@Override
protected void onBindViewHolder(@NonNull TodoHolder holder, int position, @NonNull Todo model) {
holder.textViewTitle.setText(model.getTitle());
holder.textViewDescription.setText(model.getDescription());
}

@NonNull
@Override
public TodoHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
viewItem = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_todo,
parent, false);
return new TodoHolder(viewItem);
}

public void deleteItem(final int position) {
getSnapshots().getSnapshot(position).getReference().delete();
}

public void setDoneItem(int position){
getSnapshots().getSnapshot(position).getReference().update("done", true);
viewItem.setEnabled(false);
}

public void setOnItemClickListener(OnItemClickListener listener){
this.listener = listener;
}

public interface OnItemClickListener{
void onItemClick (DocumentSnapshot documentSnapshot, int position);
}

public class TodoHolder extends RecyclerView.ViewHolder {
private TextView textViewTitle;
private TextView textViewDescription;
private String documentID;

public TodoHolder(View itemView) {
super(itemView);
textViewTitle = itemView.findViewById(R.id.todo_title);
textViewDescription = itemView.findViewById(R.id.todo_description);


itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int position = getAdapterPosition();
if(position != RecyclerView.NO_POSITION && listener != null){
listener.onItemClick(getSnapshots().getSnapshot(position), position);
}
}
});
}

}


//model class
public class Todo {

private String title;
private String description;
private String author;
private boolean done;
private int position;
private Date created;

public Todo(){} // Needed for Firebase

public Todo(String title, String description, String author, boolean done, int position, Date created) {
this.title = title;
this.description = description;
this.author = author;
this.done = done;
this.position = position;
this.created = created;
}

public String getTitle() {
return title;
}

public String getDescription() {
return description;
}

public String getAuthor() {
return author;
}

public boolean getDone() {
return done;
}

public void setTitle(String title) {
this.title = title;
}

public void setDescription(String description) {
this.description = description;
}

public void setAuthor(String author) {
this.author = author;
}

public void setDone(boolean done) {
this.done = done;
}

public int getPosition() {
return position;
}

public void setPosition(int position) {
this.position = position;
}

@ServerTimestamp
public Date getCreated() {
return created;
}

public void setCreated(Date created) {
this.created = created;
}

//数据库结构

“待办事项”集合文档字段:作者字符串、创建时间戳、描述字符串、完成 boolean 值、位置编号、标题字符串

我希望拖放位置更改在 Firestore 中持久存在,并且 RecyclerView 仅显示项目的正确移动,而不会显示其他更改。

最佳答案

我实现这一目标的方法是存储位置并在必要时更新它。如果给每个项目一个排名,那么只需要在该项目受到影响时写入该项目即可。

我只有一个重新排序功能,每次移动项目时都会写入新的排名,如果我将项目 15 移动到位置 1,我需要更改 1-15 的所有位置。根据功能的频率,您可以变得聪明,例如存储排名并仅在没有其他更改的几秒钟后更新它(以避免用户非常快速地进行 50 次更改并每次更新)。

这不是最佳选择,但通过数据库进行持久化似乎需要专用字段,因此需要这种方法。

关于java - 垂直拖放到 RecyclerView 上后如何保留 firestore 中的项目位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56960740/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com