【问题标题】:Firestore query adding same data on document change - AndroidFirestore 查询在文档更改上添加相同的数据 - Android
【发布时间】:2019-07-16 12:18:54
【问题描述】:

我正在使用这种方法来加载活跃用户:

private void loadActiveUsers() {

    usersList.clear();

    Query activeUsersQuery = firebaseFirestore.collection("Users").whereEqualTo("active", true);
    activeUsersQuery.addSnapshotListener(new EventListener<QuerySnapshot>() {
        @Override
        public void onEvent(@Nullable QuerySnapshot queryDocumentSnapshots, @Nullable FirebaseFirestoreException e) {

            for (DocumentChange documentChange: queryDocumentSnapshots.getDocumentChanges()) {

                if (documentChange.getType() == DocumentChange.Type.ADDED) {

                    String user_id = documentChange.getDocument().getId();
                    Users users = documentChange.getDocument().toObject(Users.class).withId(user_id);
                    usersList.add(users);

                    activeUsersRecyclerAdapter.notifyDataSetChanged();

                }

                if (documentChange.getType() == DocumentChange.Type.MODIFIED) {

                    String user_id = documentChange.getDocument().getId();
                    Users users = documentChange.getDocument().toObject(Users.class).withId(user_id);
                    usersList.remove(users);
                    usersList.clear();
                    usersList.add(users);

                    activeUsersRecyclerAdapter.notifyDataSetChanged();

                }

                if (documentChange.getType() == DocumentChange.Type.REMOVED) {

                    String user_id = documentChange.getDocument().getId();
                    Users users = documentChange.getDocument().toObject(Users.class).withId(user_id);
                    usersList.remove(users);

                    activeUsersRecyclerAdapter.notifyDataSetChanged();

                }

            }

        }
    });

}

当一个新用户变得活跃时,他的名字会多次添加到列表中。单击刷新按钮时,列表恢复正常。如果他不活动,recyclerview 就会搞砸。

这是适配器:

public class ActiveUsersRecyclerAdapter extends RecyclerView.Adapter<ActiveUsersRecyclerAdapter.ViewHolder> {

public List<Users> usersList;
public Context context;

public ActiveUsersRecyclerAdapter(Context context, List<Users> usersList) {

    this.context = context;
    this.usersList = usersList;

}

@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int i) {

    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.user_list_item, parent, false);
    context = parent.getContext();
    return new ViewHolder(view);


}

@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {

    final String userID = usersList.get(position).UserID;

    String image = usersList.get(position).getImage();
    holder.setImage(image);

    String username = usersList.get(position).getUsername();
    holder.setUsername(username);

    holder.view.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            Toast.makeText(context, userID, Toast.LENGTH_SHORT).show();

        }
    });

}

@Override
public int getItemCount() {

    return usersList.size();

}

public class ViewHolder extends RecyclerView.ViewHolder {

    public View view;

    public CircleImageView imageView;
    public TextView usernameView;

    public ViewHolder(@NonNull View itemView) {

        super(itemView);

        view = itemView;

    }

    public void setImage(String image) {

        imageView = view.findViewById(R.id.user_image);
        Glide.with(context).load(image).into(imageView);

    }

    public void setUsername(String username) {

        usernameView = view.findViewById(R.id.user_username);
        usernameView.setText(username);

    }

}

}

我尝试了holder.setIsRecyclable(false),但没有成功。

如何防止数据被多次添加或防止recycler搞砸?

【问题讨论】:

  • 代码乍一看还不错?您是否已经在调试器中单步执行onEvent 以查看其行为是否符合您的预期?您多久拨打一次loadActiveUsers
  • @FrankvanPuffelen 在活动启动和点击刷新按钮时调用它
  • 那就可以解释了。由于您使用addSnapshotListener 添加了一个侦听器,因此在附加它后它将保持活动状态。你不需要回忆它。

标签: android google-cloud-firestore android-recyclerview


【解决方案1】:

当您调用addSnapshotListener 时,您正在为数据添加一个永久监听器。当您附加侦听器时,它会立即开始加载数据并调用您的onEvent,但它也会保持主动监控数据并在有任何相关更改时再次调用onEvent(例如当另一个用户变为活动状态时)。因此,如果您使用addSnapshotListener,则无需多次调用loadActiveUsers

如果您只想在调用loadActiveUsers 时加载活动用户,请考虑改用get() 方法。当您调用 get() 时,数据只会加载一次。因此,在这种情况下,您可以在用户点击刷新以加载更新的数据时调用loadActiveUsers

一般来说,我建议使用addSnapshotListener,因为它使您的 UI 能够响应数据的变化(无论它们来自何处)。但在这种情况下,请确保只附加一次侦听器(通常在创建 Activity 时)并在完成时将其移除(通常在 Activity 停止、暂停或隐藏时)。

【讨论】:

  • 但如果用户名变为非活动状态,则列表不会刷新。或者,如果他再次处于活动状态,则该项目被复制。您知道如何按用户名订购查询吗?
  • 如果您使用addSnapshotListener 并且用户变为非活动状态,则onEvent 将触发该文档并带有DocumentChange.Type.REMOVED
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-11
  • 1970-01-01
  • 2020-06-18
相关资源
最近更新 更多