我希望有人能帮助我了解回收器是如何工作的,这样我就可以正确地管理数据。
我有两个回收器,它们获得一个任务列表(当前为6个)和一个字符串,为每个字母创建一个项目(例如,StoneAge创建8个项目)。回收者本身工作得很好。两者都正确地显示列表,然而,我认为我对两者的问题归结为同一件事。
任务回收器最好地突出了这个问题。我希望每个任务根据集合中返回的Status值显示不同的内容。所以,如果我的集合是任务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,它将能够设置它。
谁能提供一个简单的例子/解释一下我如何正确地处理这个职位?OK。这是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的代码,因为这是不相关的(并使代码更混乱!)
重复最后一个颜色的问题不是关于RecyclerView工作的方式,而是关于您为适配器提供的数据。在MainActivity
类中,您已经定义了bgColor
变量,并且将该变量传递给回收器视图中的所有ItemsViewModel
项目。bgColor
是一个有一个引用的对象,它被传递给你的RecyclerView的所有项。每次将它添加到list时,都会改变它的值,但记住它仍然是同一个对象。所以当你改变这个对象的值时,列表中所有项目的颜色都会改变,因为它们的颜色仍然指向bgColor
,而你已经改变了bgColor的值。因此,当您添加最后一个ItemsViewModel
到列表中,并更改最后一次bgColor
时,列表中所有项目的颜色将更改为最后一个bgColor
值。
要解决这个问题,您只需要在for循环中定义bgColor
,以便为列表中的每个项目定义一个具有不同引用的新对象。
for (document in result) {
var bgColor: Int = 0
....