应用程序在 recyclerview 滚动 android kotlin 时崩溃

Posted

技术标签:

【中文标题】应用程序在 recyclerview 滚动 android kotlin 时崩溃【英文标题】:App crash on recyclerview scrolling android kotlin 【发布时间】:2022-01-24 05:50:06 【问题描述】:

我正在做一个项目,将数据从 firebase 加载到 recyclerview 中。 recyclerview 似乎工作得很好,但是当我尝试滚动它直到帖子结束时,它总是使应用程序崩溃。如果我不滚动到最后的帖子,它就不会崩溃,这对我来说很奇怪。在 logcat 中它只显示一个错误“无法获取数据分析器......”。我对此一无所知。请帮忙!

代码如下:

package teacher

import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.amazontutoringcenter.R
import com.example.amazontutoringcenter.databinding.ActivityTeacherLessonPlanBinding
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.firestore.*
import com.google.firebase.firestore.EventListener
import com.squareup.picasso.Picasso
import student.StudentPostData
import kotlin.collections.ArrayList

class TeacherLessonPlan: AppCompatActivity() 

    private lateinit var binding : ActivityTeacherLessonPlanBinding
    private lateinit var auth: FirebaseAuth
    private lateinit var firebaseFirestore: FirebaseFirestore
    private lateinit var userRecyclerview: RecyclerView
    private lateinit var studentLessonPlanAdapter: LessonPlanAdapter
    private lateinit var userArrayList: ArrayList<StudentPostData>
    private lateinit var studentName: String
    private lateinit var studentProfileUri : String

    override fun onCreate(savedInstanceState: Bundle?)
        super.onCreate(savedInstanceState)
        binding = ActivityTeacherLessonPlanBinding.inflate(layoutInflater)
        val view = binding.root
        setContentView(view)

        auth = FirebaseAuth.getInstance()

        // post lesson plan

        binding.tvStudentName.setOnClickListener 

                intent = Intent(this, TeacherLessonPlanPost::class.java)
                intent.putExtra("studentName", studentName)
                intent.putExtra("studentProfileUri", studentProfileUri)
                startActivity(intent)
        

            // get passing data to display profile and name
            var b: Bundle = intent.extras!!
            studentProfileUri = b.getString("studentProfileUri").toString()
            studentName = b.getString("studentName").toString()
            Picasso.get().load(studentProfileUri).fit()
                .centerCrop().into(binding.imageStudentProfile)


            userRecyclerview = findViewById(R.id.recyclerViewStudentLessonPlan)
            userRecyclerview.layoutManager = LinearLayoutManager(this)

            userArrayList = arrayListOf()
            studentLessonPlanAdapter = LessonPlanAdapter(userArrayList)
            userRecyclerview.adapter = studentLessonPlanAdapter

        getStudentLessonPlanPost()

    

    private fun getStudentLessonPlanPost() 
        val uid = auth.currentUser!!.uid
        firebaseFirestore = FirebaseFirestore.getInstance()
        firebaseFirestore.collection("student").document("lesson plan")
            .collection("$uid")
            .addSnapshotListener(object : EventListener<QuerySnapshot> 
                override fun onEvent(value: QuerySnapshot?, error: FirebaseFirestoreException?) 
                    if(error != null)
                        Log.d("check error", error.message.toString())
                        return
                    

                    for(dc : DocumentChange in value?.documentChanges!!)

                        if(dc.type == DocumentChange.Type.ADDED)

                            userArrayList.add(dc.document.toObject(StudentPostData::class.java))
                            userArrayList.sortByDescending 
                                it.date
                            
                        
                    

                    studentLessonPlanAdapter.notifyDataSetChanged()
                

            )

    

    inner class LessonPlanAdapter(private val userList : ArrayList<StudentPostData>) : RecyclerView.Adapter<LessonPlanAdapter.MyViewHolder>() 


        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder 

            val itemView = LayoutInflater.from(parent.context).inflate(
                R.layout.student_lesson_plan,
                parent,false)
            return MyViewHolder(itemView)

        

        override fun getItemCount(): Int 

            return userList.size
        

        inner class MyViewHolder(itemView : View) : RecyclerView.ViewHolder(itemView)

            val txLessonPlanDescription : TextView = itemView.findViewById(R.id.txLessonPlanDescription)
            val imageStudentLessonPlan : ImageView = itemView.findViewById(R.id.imageStudentLessonPlan)

            val imageStudentProfilePost : ImageView = itemView.findViewById(R.id.imageStudentProfilePost)
            val tvStudentNamePost : TextView = itemView.findViewById(R.id.tvStudentNamePost)

            // date on the post
            val textDate : TextView = itemView.findViewById(R.id.txLessonPlanDate)

        

        override fun onBindViewHolder(holder: MyViewHolder, position: Int) 

            val currentitem = userList[position]

            holder.txLessonPlanDescription.text = currentitem.description
            holder.textDate.text = currentitem.date
            Picasso.get().load(currentitem.imageUri)
                .into(holder.imageStudentLessonPlan)

            holder.tvStudentNamePost.text = studentName
            Picasso.get().load(studentProfileUri).fit()
                .centerCrop().into(holder.imageStudentProfilePost)

        

    

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical">

    <LinearLayout
        android:id="@+id/relativeLayout"
        android:orientation="horizontal"
        android:layout_
        android:layout_
        android:padding="15dp"
        android:elevation="10dp"
        android:layout_marginBottom="0dp"
        android:layout_marginLeft="5dp"
        android:layout_marginRight="5dp"
        android:layout_marginTop="5dp">

        <com.google.android.material.imageview.ShapeableImageView
            android:id="@+id/imageStudentProfile"
            android:layout_
            android:layout_
            android:layout_marginStart="5dp"
            android:layout_marginTop="50dp"
            android:src="@drawable/ic_profile"
            app:shapeAppearanceOverlay="@style/circular"
            app:strokeColor="#0AF3D0"
            android:layout_gravity="center_horizontal"
            app:strokeWidth="1dp" />

        <TextView
            android:id="@+id/tvStudentName"
            android:layout_
            android:layout_
            android:layout_marginLeft="10dp"
            android:padding="5dp"
            android:fontFamily="serif"
            android:clickable="true"
            android:hint="បង្ហោះកិច្ចតែងការបង្រៀន..."
            android:background="@drawable/border_square"
            android:textColor="#2196F3"
            android:textSize="20dp" />

    </LinearLayout>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerViewStudentLessonPlan"
        android:layout_
        android:layout_
        tools:listitem="@layout/student_lesson_plan">

    </androidx.recyclerview.widget.RecyclerView>

</LinearLayout>

【问题讨论】:

如果您可以分享您的错误,那将会很有帮助。 StudentPostData 对象是否有可能在其某个字段中具有空值,并且您尝试将其分配给适配器中的视图? 如果应用程序崩溃,会有一个堆栈跟踪。请在 logcat 上查找,并将其添加到您的问题中。除此之外,我认为这篇名为How to paginate Firestore using Paging 3 on Android? 的文章可能会有所帮助。 @MohammadRezaKhahani 好的,我会更新它,但就像我说的第 n 个特别,因为它没有显示任何错误。 @AlexMamo 啊,你让我想起了。有时应用程序不会崩溃,但会进入上一个活动 【参考方案1】:

由于您在全局范围内使用 userArrayList 变量为适配器提供服务,因此数据尝试删除 LessonPlanAdapter 类参数并仅使用全局变量来填充它:

inner class LessonPlanAdapter() : RecyclerView.Adapter<LessonPlanAdapter.MyViewHolder>() 

    ...

    override fun getItemCount(): Int = userArrayList.size

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) 
        val currentitem = userArrayList[position]
            
        ...
    

我认为问题可能与包含数据的类变量未正确更新有关。

这可能导致到达列表底部时出现索引越界异常。

【讨论】:

谢谢男人。我会考虑的【参考方案2】:

解决了!我不确定问题是什么,但我可以通过删除我在 firestore 中的所有文档然后尝试添加新文档来解决它。现在它工作正常。谢谢大家的帮助!

【讨论】:

以上是关于应用程序在 recyclerview 滚动 android kotlin 时崩溃的主要内容,如果未能解决你的问题,请参考以下文章

确定何时显示 recyclerview 快速滚动拇指?

如何使用 videoPlayer 滚动 recyclerview 视频帧

RecyclerView中的CardView垂直滚动

如何为无限滚动的 RecyclerView 绘制背景

RecyclerView在刷新时滚动时崩溃

为啥直到在选项卡之间滚动才会显示 recyclerview 项目?