【问题标题】:How to get document id in In FirestorePagingAdapter?如何在 FirestorePagingAdapter 中获取文档 ID?
【发布时间】:2019-05-09 15:08:52
【问题描述】:

我正在尝试使用FirestorePagingAdapter 来显示我的firestore 数据库中所有用户的列表。我使用 FirestorePagingAdapter 而不是 FirestoreRecyclerAdapter 来最小化读取次数,因为 FirestorePagingAdapter 不会读取整个文档列表,而 FirestoreRecyclerAdapter 会读取。我能够成功显示分页列表,但我需要在其上实现onClickListener,并且在单击每个项目时,我需要打开另一个活动,该活动显示被单击的特定用户的详细描述。为此,我需要将点击用户的 documentId 传递给下一个活动。

但不幸的是,FirestorePagingAdapter 没有 getSnapshots() 方法,因此我使用 getSnapshots().getSnapshot(position).getId()。

另一方面,FirestoreRecyclerAdapter 有这个方法,这使得获取文档 id 变得非常简单。像这样:How to get document id or name in Android in Firestore db for passing on to another activity?

// Query to fetch documents from user collection ordered by name
Query query = FirebaseFirestore.getInstance().collection("users")
                .orderBy("name");

// Setting the pagination configuration
PagedList.Config config = new PagedList.Config.Builder()
                .setEnablePlaceholders(false)
                .setPrefetchDistance(10)
                .setPageSize(20)
                .build();


FirestorePagingOptions<User> firestorePagingOptions = new FirestorePagingOptions.Builder<User>()
                .setLifecycleOwner(this)
                .setQuery(query, config, User.class)
                .build();

firestorePagingAdapter =
                new FirestorePagingAdapter<User, UserViewHolder>(firestorePagingOptions){

                    @NonNull
                    @Override
                    public UserViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
                        View view = LayoutInflater.from(parent.getContext())
                                .inflate(R.layout.single_user_layout, parent, false);

                        return new UserViewHolder(view);
                    }

                    @Override
                    protected void onBindViewHolder(@NonNull UserViewHolder holder, int position, @NonNull User user) {
                        holder.setUserName(user.name);
                        holder.setStatus(user.status);
                        holder.setThumbImage(user.thumb_image, UsersActivity.this);


                        holder.mView.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                Intent userProfileIntent = new Intent(UsersActivity.this, UserProfileActivity.class);
                                // Need to fetch the user_id to pass it as intent extra
                                // String user_id = getSnapshots().getSnapshot(position).getId();
                                // userProfileIntent.putExtra("user_id", user_id);
                                startActivity(userProfileIntent);
                            }
                        });
                    }
                };

【问题讨论】:

  • 或者您可以跳过使用 FirestorePagingAdapter 并自己将查询结果绑定到 RecyclerView。推荐的现代应用架构使用带有 Firebase SDK 的 Android Jetpack,如本仓库所示。 github.com/CodingDoug/firebase-jetpack

标签: java android firebase google-cloud-firestore android-paging


【解决方案1】:

我可以通过在setQuery 方法中使用SnapshotParser 来做到这一点。通过这个,我能够修改从 Firestore 获得的对象。 documentSnapshot.getId() 方法返回文档 id。

FirestorePagingOptions<User> firestorePagingOptions = new FirestorePagingOptions.Builder<User>()
                .setLifecycleOwner(this)
                .setQuery(query, config, new SnapshotParser<User>() {
                    @NonNull
                    @Override
                    public User parseSnapshot(@NonNull DocumentSnapshot snapshot) {
                        User user = snapshot.toObject(User.class);
                        user.userId = snapshot.getId();
                        return user;
                    }
                })
                .build();

在 User 类中,我刚刚在 User 类中添加了另一个字段“String userId”。我的 firestore 文档中不存在 userId 字段。 在onClickListener 中,我可以直接使用user.userId 获取文档ID 并将其发送给其他活动。

【讨论】:

  • 还在工作吗?我需要获取更新文档,但我现在正在使用 FirestorePagingAdapter
【解决方案2】:

在尝试从 itemView 访问文档快照时,我发现 this

itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                int pos = getAdapterPosition();
                if (pos != RecyclerView.NO_POSITION && listener != null) {
                    String docId = getItem(pos).getId();
                    Toast.makeText(context, "doc Id: "+docId, Toast.LENGTH_SHORT).show();
                    //listener.onItemClick(getSnapshots().getSnapshot(pos), pos, docId);
                    listener.onItemClick(getItem(pos), pos, docId); 
                }
            }
        });

here 所述,getItem() 返回项目的数据对象。

【讨论】:

    【解决方案3】:

    正如您已经注意到的那样:

    String id = getSnapshots().getSnapshot(position).getId();
    

    不起作用,它仅在使用FirestoreRecyclerAdapter 时起作用。所以要解决这个问题,您需要将文档的 id 存储为文档的属性。如果文档的 id 是来自 Firebase 身份验证的用户的 id,那么只需存储 uid。如果您没有使用uid,请在创建新对象时获取文档的 id 并将其传递给User 构造函数:

    FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
    CollectionReference usersRef = rootRef.collection("users");
    String id = eventsRef.document().getId();
    User user = new User(id, name, status, thumb_image);
    usersRef.document(id).set(user);
    

    【讨论】:

    • 这是一种正确的方法还是应该创建我自己的适配器来扩展FirestoreRecyclerAdapter,然后使用查询游标对数据进行分页(firebase.google.com/docs/firestore/query-data/query-cursors)。
    • 是的,这是正确的方法。在这种情况下,无需创建自定义适配器,因为您只需将用户的 id 传递给构造函数,然后在 onClick() 方法中使用 user.id
    • 亚历克斯,请参阅my answer。我能够找到一种既不涉及将 uid 存储在文档中也不涉及使用自定义适配器的中间方式。
    • 这是一个很好的解决方案,但它只能在本地解决问题。我为什么这么说?如果您稍后在项目中发现自己需要根据他的 id 从数据库中删除用户,请注意您不能这样做。这是因为数据库中不存在用户ID,因此您无法执行这样的查询,对吧?
    • @user1823280 它算作初始文档读取,不是附加文档读取。
    【解决方案4】:

    我花了一天时间尝试获取文档的 ID,因为我现在正在使用 FirestorePagingAdapter。对于 Kotlin,这对我有用

    override fun onBindViewHolder(viewHolder: LyricViewHolder, position: Int, song: Lyric) {
                    // Bind to ViewHolder
                    viewHolder.bind(song)
    
                    viewHolder.itemView.setOnClickListener { view ->
    
                        val id = getItem(position)?.id
    
                        var bundle = bundleOf("id" to id)
                        view.findNavController().navigate(R.id.songDetailFragment, bundle)
                    }
                }
    

    希望这在不久的将来对其他人有所帮助。如果有人感到困惑,可以发布完整的代码并充分解释。编码愉快!

    【讨论】:

      【解决方案5】:

      试试这个

      getSnapshots().getSnapshot(position).getId()
      

      【讨论】:

      • 引用问题“但不幸的是,FirestorePagingAdapter 没有 getSnapshots() 方法,因此我使用 getSnapshots().getSnapshot(position).getId()。”
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-12-23
      • 2020-07-18
      • 2020-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-02
      相关资源
      最近更新 更多