为什么我的Recyclerview会在随机位置添加新项目?

huangapple go评论153阅读模式
英文:

Why does my Recyclerview add new items at random positions?

问题

在详细阅读了如何在顶部(或底部)添加项目的内容后,我意识到 list.add(position, item) 结合 notifyDataSetChanged() 是在顶部(索引 0)添加项目的正确方式。然而,在我的代码中,即使我这样做了,我的 RecyclerView 仍然在随机位置添加项目。以下是我的 CommentsActivity 代码:

class CommentsActivity : AppCompatActivity() {
    // ...(省略其他部分)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // ...(省略其他部分)

        val layoutManager = LinearLayoutManager(this)
        layoutManager.reverseLayout = true
        layoutManager.stackFromEnd = true

        commentsActivityRecyclerView!!.layoutManager = layoutManager

        commentsList = ArrayList()
        commentAdapterView = CommentsAdapter(this, commentsList as ArrayList<CommentsModel>)
        commentsActivityRecyclerView!!.adapter = commentAdapterView
        commentsActivityRecyclerView!!.setHasFixedSize(true)

        LoadAndDisplayComments()
    }

    // ...(省略其他部分)

    private fun LoadAndDisplayComments() {
        val commentsRef = dbRef.child("Comments").child(clickedPostUid)

        commentsRef.addValueEventListener(object : ValueEventListener {
            override fun onCancelled(p0: DatabaseError) {
                TODO("Not yet implemented")
            }

            override fun onDataChange(p0: DataSnapshot) {
                if (p0.exists()) {
                    commentsList!!.clear()
                    for (snapshot in p0.children) {
                        val getCommentDetails = snapshot.getValue(CommentsModel::class.java)
                        if (getCommentDetails != null) {
                            commentsList!!.add(0, getCommentDetails)
                        }
                    }

                    commentAdapterView!!.notifyDataSetChanged()
                } else {
                    Toast.makeText(this@CommentsActivity, "No comments", Toast.LENGTH_SHORT).show()
                }
            }
        })
    }
}

这是我的 CommentsAdapter:

class CommentsAdapter(
    private var commentsContext: Context,
    private var commentsList: MutableList<CommentsModel>
) : RecyclerView.Adapter<CommentsAdapter.CommentsViewHolder>() {
    // ...(省略其他部分)

    override fun onBindViewHolder(holder: CommentsViewHolder, position: Int) {
        val currentUser = FirebaseAuth.getInstance().currentUser!!
        val comment = commentsList!![position]
        holder.showComment.text = comment.comment
    }
}

我希望新的评论可以显示在 RecyclerView 的顶部或底部。我知道如何使用 .SmoothScroll 滚动到索引 0。如果需要的话,我可以贴出 XML。谢谢。

英文:

After much reading on how to add an item to the top (or bottom), I realized that list.add(position, item) along with notifyDataSetChanged() is the correct way to add an item at the top (index 0). However, in my code, even after doing that, my RecyclerView adds positions at random places. Below is my CommentsActivity code:

class CommentsActivity : AppCompatActivity() {

private var clickedPostUid = &quot;&quot;
private var currentUserUid = &quot;&quot;
private lateinit var binding_commentsActivity: ActivityCommentsBinding
private val currentUserUID = FirebaseAuth.getInstance().currentUser?.uid!!
private val dbRef = FirebaseDatabase.getInstance().reference
private val uidRef = currentUserUID.let { dbRef.child(&quot;Users&quot;).child(it) }
private var commentAdapterView: CommentsAdapter? = null
private var commentsList: MutableList&lt;CommentsModel&gt;? = null
var commentsActivityRecyclerView: RecyclerView? = null

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    binding_commentsActivity = ActivityCommentsBinding.inflate(layoutInflater)
    clickedPostUid = intent.getStringExtra(&quot;keyIdentifierPostUid&quot;)!!
    currentUserUid = intent.getStringExtra(&quot;keyIdentifierCurrentUserUid&quot;)!!

    commentsActivityRecyclerView =
        binding_commentsActivity.commentsActivityRecyclerView


    val layoutManager = LinearLayoutManager(this)
    layoutManager.reverseLayout = true
    layoutManager.stackFromEnd = true

    commentsActivityRecyclerView!!.layoutManager = layoutManager

    commentsList = ArrayList()
    commentAdapterView = CommentsAdapter(this, commentsList as ArrayList&lt;CommentsModel&gt;)
    commentsActivityRecyclerView!!.adapter = commentAdapterView
    commentsActivityRecyclerView!!.setHasFixedSize(true)

    LoadAndDisplayComments()

And this is my LoadAndDisplayComments()

private fun LoadAndDisplayComments() {
    val commentsRef = dbRef.child(&quot;Comments&quot;).child(clickedPostUid)

    commentsRef.addValueEventListener(object : ValueEventListener {
        override fun onCancelled(p0: DatabaseError) {
            TODO(&quot;Not yet implemented&quot;)
        }

        override fun onDataChange(p0: DataSnapshot) {
            if (p0.exists())
            {
                commentsList!!.clear()
                for (snapshot in p0.children)
                {
                    val getCommentDetails = snapshot.getValue(CommentsModel::class.java)
                    if (getCommentDetails != null) {
                        commentsList!!.add(0,getCommentDetails)
                    }
                }

                commentAdapterView!!.notifyDataSetChanged()
            }
            else{
                Toast.makeText(this@CommentsActivity, &quot;No comments&quot; , Toast.LENGTH_SHORT).show()
            }
        }
    })
}

This is my comments adapter

class CommentsAdapter(
private var commentsContext : Context,
private var commentsList: MutableList&lt;CommentsModel&gt;
) : RecyclerView.Adapter&lt;CommentsAdapter.CommentsViewHolder&gt;()
{
inner class CommentsViewHolder(@NonNull itemView: View) : RecyclerView.ViewHolder(itemView) {
    val showComment : TextView = itemView.comments_recview_item_comment
    val showImage : CircleImageView = itemView.comments_recview_item_profile_image
    val showUsername : TextView = itemView.comments_recview_item_username

}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CommentsViewHolder {
    val itemView = LayoutInflater.from(commentsContext)
        .inflate(R.layout.comment_recyclerview_item, parent, false)

    return CommentsViewHolder(itemView)
}

override fun getItemCount(): Int {
    return commentsList!!.size
}

override fun onBindViewHolder(holder: CommentsViewHolder, position: Int) {

    val currentUser = FirebaseAuth.getInstance().currentUser!!
    val comment = commentsList!![position]
    holder.showComment.text = comment.comment
}

I need that a new comment to be displayed at the top or bottom of the recyclerview. I know how to scroll to 0 index using .SmoothScroll. Would be happy to post the XML if needed. Thank you.

答案1

得分: -1

原来问题不在于RecyclerView。是我在数据库中存储值的方式有问题。我在Firebase中为我的值创建了一个唯一的Id,这导致了错误。相反,我使用了.push来生成唯一键,这样就可以正常工作。

错误的方法(或者说不是我想要的方法):

val uniqueCommentId = UUID.randomUUID().toString()
        .replace("-", "").toUpperCase(Locale.ROOT)
    val postCommentsRef = FirebaseDatabase.getInstance().reference
        .child("Comments")
        .child(postId).child(uniqueCommentId)
   postCommentRef.setValue()

更好的方法:

val postCommentsRef = FirebaseDatabase.getInstance().reference
        .child("Comments")
        .child(postId)

    val commentMap = HashMap<String, Any>()
    commentMap["userUid"] = currentUserUid
    commentMap["postId"] = postId
    commentMap["comment"] = comment

    postCommentsRef.push().setValue(commentMap)

在这之后,对我来说运行良好。

英文:

Turns out the error was not in the RecyclerView. It was the way I was storing the values in the database. I was creating a unique Id for my values in Firebase that was causing the error. Instead I used .push to generate unique keys and it worked fine.

Wrong approach (or just not what I wanted):

val uniqueCommentId = UUID.randomUUID().toString()
        .replace(&quot;-&quot;,&quot;&quot;).toUpperCase(Locale.ROOT)
    val postCommentsRef = FirebaseDatabase.getInstance().reference
        .child(&quot;Comments&quot;)
        .child(postId).child(uniqueCommentId )
   postCommentRef.setValue()

Better approach:

 val postCommentsRef = FirebaseDatabase.getInstance().reference
        .child(&quot;Comments&quot;)
        .child(postId)

    val commentMap = HashMap&lt;String, Any&gt;()
    commentMap[&quot;userUid&quot;] = currentUserUid
    commentMap[&quot;postId&quot;] = postId
    commentMap[&quot;comment&quot;] = comment

    postCommentsRef.push().setValue(commentMap)

Worked fine for me after this.

huangapple
  • 本文由 发表于 2020年6月5日 23:06:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/62218495.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定