首页 > 解决方案 > 使用 Kotlin 在 FirestoreRecycler 适配器上使用 UID 检索显示配置文件?

问题描述

我在从 Firebase Firestore 为我的 Recycler Adapter 正确检索信息时遇到了困难。我不确定我可能做错了什么,但我使用了文档参考来获取必填字段,但现在它似乎只是一遍又一遍地复制相同的东西,我希望它显示每个创建的用户配置文件并将其显示在我的 RecyclerAdapter但我不确定我应该做什么并且尝试了不同的方法但得到了一个

我的模型类“用户”上的“没有设置器/字段错误”。

这是我的 Firebase 架构 这是它正在输出的内容

到目前为止,这就是我的代码

[更新] 这是我导入的

import Models.User
import android.content.Intent
import android.content.res.Configuration
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.appcompat.widget.Toolbar
import androidx.core.view.GravityCompat
import androidx.drawerlayout.widget.DrawerLayout
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.firebase.ui.firestore.FirestoreRecyclerAdapter
import com.firebase.ui.firestore.FirestoreRecyclerOptions
import com.google.android.material.navigation.NavigationView
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.firestore.*
import com.squareup.picasso.Picasso
import de.hdodenhof.circleimageview.CircleImageView
import kotlinx.android.synthetic.main.all_nearby_users.*
import kotlinx.android.synthetic.main.toolbar_layout.*

创建

       auth = FirebaseAuth.getInstance()
        val customUserId = auth.currentUser!!.uid
        val db = FirebaseFirestore.getInstance()
        val userRef = db.collection("sUsers").document(customUserId)
        val userQuery = db.collection("sUsers").orderBy("Full Name", Query.Direction.DESCENDING).limit(10)

//User List Layout
        all_users_nearby_list.layoutManager = LinearLayoutManager(this)

        //Firestore
        val firestoreRecyclerOptions: FirestoreRecyclerOptions<Users> = FirestoreRecyclerOptions.Builder<Users>()
            .setQuery(userQuery, Users::class.java)
            .build()
        adapter = UserFirestoreRecyclerAdapter(firestoreRecyclerOptions)
        all_users_nearby_list.adapter = adapter

Firestore 回收器适配器

private inner class UserFirestoreRecyclerAdapter internal constructor
        (firestoreRecyclerOptions: FirestoreRecyclerOptions<Users>): FirestoreRecyclerAdapter<Users, UserViewHolder>(firestoreRecyclerOptions) {

            override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
                val userView = LayoutInflater.from(parent.context)
                    .inflate(R.layout.display_users_profile, parent, false)

                return UserViewHolder(userView)
            }

            override fun onBindViewHolder(holder: UserViewHolder, position: Int, model: Users) {

                holder.setFullname(model.fullname)
                holder.setProfileimage(model.profileImage)

            }

        }

用户视图持有者


   private inner class UserViewHolder internal constructor (private val pView: View) : RecyclerView.ViewHolder(pView) {


        internal fun setFullname(fullname: String) {
            val username = pView.findViewById<TextView>(R.id.usernameTextView)
            val db = FirebaseFirestore.getInstance()
            val docRef = db.collection("sUsers").document(auth.currentUser!!.uid)
            docRef.get()
                .addOnSuccessListener { document ->
                    if (document != null) {
                        Log.d("HomeActivity", "DocumentSnapshot data: ${document.data}")
                        username.text = document.getString("Full Name")

                    } else {
                        Log.d("HomeActivity", "No such document")
                    }
                }
                .addOnFailureListener { exception ->
                    Log.d("HomeActivity", "get failed with ", exception)
                }


            username.text = fullname
            Log.d("HomeActivity", "Current Data: " + fullname)
        }

        internal fun setProfileimage(profileImage: String) {
            val userProfileImage = pView.findViewById<CircleImageView>(R.id.profileUserImage)
            Picasso.get().load(profileImage).into(userProfileImage)
        }

    }

模型类

package Models

    class Users(
    var fullname: String= "",
    var profileImage: String= "",
    var uid: String? = "",
    var haircut: Boolean? = null,
    var waxing: Boolean? = null,
    var nails: Boolean? = null,
    var profileRatingBar: Float? = 1.0f
)

我的 onStart 和 onStop


   override fun onStart() {
        super.onStart()
        adapter!!.startListening()
    }

    override fun onStop() {
        super.onStop()

        if (adapter != null) {
            adapter!!.stopListening()
        }
    }

标签: kotlingoogle-cloud-firestoreandroid-recyclerview

解决方案


这就是我将如何编写您的 RecyclerView。关键点:

  • 不要在 ViewHolder 中进行第二次 FireStore 查询
  • 您的 Firestore 架构必须与您的模型完全匹配
  • 使用生命周期所有者而不是 onStart/onStop
  • Firebase UI 不捕获 uid;所以手动执行此操作(请参阅apply
  • ViewHolder 必须将视图“保存”为字段(以避免每次都调用 find)
  • 模型代表 1 个对象,所以我将其命名为“用户”而不是“用户”
  • 在 XML 中设置 layoutManager 以减少 onCreate 中的样板文件

布局 XML

<androidx.recyclerview.widget.RecyclerView
    ...
    app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
    tools:itemCount="5"
    tools:listitem="@layout/display_users_profile"
    ... />

创建活动

val query = FirebaseFirestore.getInstance()
    .collection("sUsers") // Why not "users" ?
    .orderBy("fullname", Query.Direction.DESCENDING)
    .limit(10)

val options = FirestoreRecyclerOptions.Builder<User>()
    .setLifeCycleOwner(this)
    .setQuery(query) { it.toObject(User::class.java)!!.apply { uid = it.id } }
    .build()

all_users_nearby_list.adapter = UserFirestoreRecyclerAdapter(options)

适配器

internal class UserFirestoreRecyclerAdapter(options: FirestoreRecyclerOptions<User>) : 
    FirestoreRecyclerAdapter<User, UserViewHolder>(options) {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = 
        LayoutInflater.from(parent.context)
            .inflate(R.layout.display_users_profile, parent, false)
            .let { UserViewHolder(it) }

    override fun onBindViewHolder(holder: UserViewHolder, position: Int, model: Users) = 
        holder.bind(model)

}

视图持有者

internal class UserViewHolder(itemView: View) : 
    RecyclerView.ViewHolder(itemView) {

    // Hold view refs
    private val usernameTextView: TextView = itemView.userNameTextView
    private val profileUserImage: ImageView = itemView.profileUserImage

    internal fun bind(model: User) {
        model.apply {
            usernameTextView.text = fullname
            Picasso.get().load(profileImage).into(profileUserImage)
        }
    }
}

模型

// Set sensible defaults here (or null if no sensible default)
data class User(
    var uid: String = "",
    var fullname: String= "",
    var profileImage: String= "",
    var haircut: Boolean = false,
    var waxing: Boolean = false,
    var nails: Boolean = false,
    var profileRatingBar: Float? = null
)

推荐阅读