Firestore查询在文档更改时添加相同的数据-Android

时间:2019-07-16 12:18:54

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

我正在使用此方法加载活跃用户:

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),但是没有用。

如何防止多次添加数据或阻止回收者搞乱?

1 个答案:

答案 0 :(得分:0)

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

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

一般而言,我还是建议使用addSnapshotListener,因为它会使您的UI响应数据中的更改(无论它们来自何处)。但是在那种情况下,请确保仅将侦听器附加一次(通常在创建活动时),并在完成后将其删除(通常在活动停止,暂停或隐藏时)。