首页 > 解决方案 > Kotlin 回收站视图

问题描述

我希望有人可以帮助我了解回收站的工作原理,以便我可以正确管理数据。

我有两个回收器,它们获取一个任务列表(当前为 6 个)和一个为每个字母创建一个项目的字符串(例如,StoneAge 创建 8 个项目)。回收商本身工作得很好。两者都正确显示列表,但是,我认为我遇到的问题归结为同一件事。

任务回收器最能突出这个问题。我希望每个任务根据集合中返回的状态值以不同方式显示。因此,如果我的设置是任务 A(完成)、任务 B(已启动)、任务 C(未启动)和任务 D(完成),我将尝试为每个状态设置不同的标题颜色。我将状态返回到回收站的集合中,并且可以为每个任务显示正确的值,但是当尝试将其应用于 textView 时,使用:

override fun onBindViewHolder(holder: ViewHolder, position : Int) {
  val t = mList[position]

  holder.txtTaskName.text = t.taskName
  holder.txtTaskName.setTextColor(t.bgColor!!)
}

它将所有内容设置为相同的颜色(列表中最后一个的颜色)。

我知道回收器会重用布局的实例,我在这里读到了类似的答案,说我需要检查位置。我不确定我是否完全理解它是如何工作的,因为我已经在使用集合中的位置。

我认为这与我对字符串的第二个回收器有问题的原因相同。它所做的是创建 8 个项目,一个用于单词的每个字母 (StoneAge) 以及一个 EditText,供用户输入以每个字母开头的单词(一首离合诗)。当视图滚动时,文本填充了以前的值,并且输入发生了一些奇怪的事情。我怀疑这与我没有正确理解回收商如何重复使用这些物品有关。我会假设因为它有正确的任务 (t) 并且知道正确的 bgColor,所以它可以设置它。

有人可以提供一个简单的例子/解释我如何正确处理这个职位吗?

好的。这是来自 MainActivity 的代码(我删除了一些与回收器无关的部分,因为它很大)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

//Definitions
        allTasksRecycler = findViewById<RecyclerView>(R.id.allTasksRecycler)
        btnAddTask = findViewById(R.id.btnAddTask)           
        lblUserTaskCount = findViewById(R.id.lblUserTaskCount)

//Recycler
        allTasksRecycler.layoutManager = LinearLayoutManager(this)

//Firebase Queries
        val data = ArrayList<ItemsViewModel>()
        var arrUserTasks: ArrayList<String>
        var arrUserTaskComplete: ArrayList<Boolean>
        var arrUserTaskStarted: ArrayList<Boolean>
        var bgColor: Int = 0
        var utID: Int

        db.collection("tasks")
            .get()
            .addOnSuccessListener { result ->
                totalTasks = result.count()
                availableTasks = totalTasks

                db.collection("userTask")
                    .whereEqualTo("userID", HWG.FBUserID)
                    .get()
                    .addOnSuccessListener { uts ->
                        if (uts.count() > 0) {
                            arrUserTasks = ArrayList(uts.count() - 1)
                            arrUserTaskComplete = ArrayList(uts.count() - 1)
                            arrUserTaskStarted = ArrayList(uts.count() - 1)

                            for (ut in uts) {
                                Log.d(HWG.TAG, "Reading ${ut.data.getValue("taskID").toString()}....")
                                arrUserTasks.add(ut.data.getValue("taskID").toString())
                                if (ut.data.getValue("isComplete") == null) {
                                    arrUserTaskComplete.add(false)
                                } 
                                else {  
arrUserTaskComplete.add(ut.data.getValue("isComplete") as Boolean)
                                }
                                if (ut.data.getValue("startDate") == null) {
                                    arrUserTaskStarted.add(false)
                                } else {
                                    arrUserTaskStarted.add(true)
                                }
                            }

                            for (document in result) {
                                utID = -1

                                Log.d(HWG.TAG,"Looking for ${document.data.getValue("name").toString()} {${arrUserTasks.size.toString()}}...")

                                utID = arrUserTasks.indexOf(document.data.getValue("name").toString())

                                if (utID >= 0) {
                                    if (arrUserTaskComplete[utID] == true) {
                                        bgColor = R.color.Completed
       
                         } else if (arrUserTaskStarted[utID] == true) {
                                    bgColor = R.color.Started
                                }
                            } else {
                                bgColor = R.color.white
                            }

                            data.add(
                                ItemsViewModel(
                                        
document.data.getValue("name").toString(),                                
document.data.getValue("description").toString(),
document.data.getValue("subject").toString(),
document.data.getValue("subjectID").toString().toInt(),
document.data.getValue("requirements").toString(),
document.data.getValue("evidence").toString(),
document.data.getValue("evidenceType").toString(),
document.data.getValue("taskType").toString(),
bgColor
                                )
                            )

                            //val adapter = AllTasksAdapter(data)
                            val adapter = AllTasksAdapter(this, data)
                            allTasksRecycler.adapter = adapter
                        }
                    }
                }
                .addOnFailureListener { }

        }
        .addOnFailureListener { exception ->
            Log.d(TAG, "Error getting documents: ", exception)
        }
}

这是适配器:

class AllTasksAdapter(val context: Activity, private val mList: List<ItemsViewModel>):RecyclerView.Adapter<AllTasksAdapter.ViewHolder>() {

    class ViewHolder(ItemView: View) : RecyclerView.ViewHolder(ItemView) {
        val subjectImage: ImageView = itemView.findViewById(R.id.subjectImage)
        val txtTaskName: TextView = itemView.findViewById(R.id.txtTaskName)
        val txtTaskRequirements: TextView = itemView.findViewById(R.id.txtTaskRequirements)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        // inflates the card_view_design view that is used to hold list item
        val view = LayoutInflater.from(parent.context)
            .inflate(R.layout.card_view_design, parent, false)

        return ViewHolder(view)
    }

    @SuppressLint("ResourceAsColor")
    @RequiresApi(Build.VERSION_CODES.O)
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {

        val t = mList[position]

        // sets the views from our itemHolder class
        if(t.subjectID == 1) //English/Topic
        {   holder.subjectImage.setImageResource(R.drawable.icons8_knowledge_sharing_80)  }
        else if(t.subjectID == 2) //Maths
        {   holder.subjectImage.setImageResource(R.drawable.icons8_maths_64)  }
        else if(t.subjectID == 3) //Science
        {   holder.subjectImage.setImageResource(R.drawable.icons8_test_tube_80)  }
        else if(t.subjectID == 4) //Reading
        {   holder.subjectImage.setImageResource(R.drawable.icons8_reading_80)  }
        else if(t.subjectID == 5) //Spelling
        {   holder.subjectImage.setImageResource(R.drawable.icons8_broken_pencil_80)  }

        holder.txtTaskName.text = t.name
        holder.txtTaskRequirements.text = t.requirements
        holder.subjectImage.tooltipText = "${t.subject} (${t.bgColor})"
        holder.txtTaskName.setTextColor(t.bgColor!!)    
        holder.itemView.setOnClickListener {
            CustomDialog(this, t).show()
        }
    }

    // return the number of the items in the list
    override fun getItemCount(): Int {
        return mList.size
    }
}

我已经删除了 CustomDialog 的代码,因为这不相关(并且使代码更加混乱!)

标签: androidkotlinandroid-recyclerview

解决方案


重复最后一种颜色的问题与 RecyclerView 的工作方式无关,而与您为适配器提供的数据有关。在MainActivity类中,您已经定义了一个bgColor变量,并且您将这个相同的变量传递给ItemsViewModel您的回收站视图中的所有项目。bgColor是一个具有一个引用的对象,它传递给 RecyclerView 的所有项目。每次将其添加到列表时都会更改其值,但请记住它仍然是同一个对象。因此,当您更改此对象的值时,列表中所有项目的颜色都会发生变化,因为所有项目的颜色仍然指向bgColor并且您已经更改了 bgColor 的值。因此,当您将最后一个添加ItemsViewModel到列表中并更改bgColor最后一次,列表中所有项目的颜色将更改为最后一个bgColor值。

为了解决这个问题,您只需要定义bgColorfor 循环的内部,因此对于列表中的每个项目,它都定义了一个具有不同引用的新对象。

      for (document in result) {

                        var bgColor: Int = 0
                        ....

推荐阅读