android - 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 的代码,因为这不相关(并且使代码更加混乱!)
解决方案
重复最后一种颜色的问题与 RecyclerView 的工作方式无关,而与您为适配器提供的数据有关。在MainActivity
类中,您已经定义了一个bgColor
变量,并且您将这个相同的变量传递给ItemsViewModel
您的回收站视图中的所有项目。bgColor
是一个具有一个引用的对象,它传递给 RecyclerView 的所有项目。每次将其添加到列表时都会更改其值,但请记住它仍然是同一个对象。因此,当您更改此对象的值时,列表中所有项目的颜色都会发生变化,因为所有项目的颜色仍然指向bgColor
并且您已经更改了 bgColor 的值。因此,当您将最后一个添加ItemsViewModel
到列表中并更改bgColor
最后一次,列表中所有项目的颜色将更改为最后一个bgColor
值。
为了解决这个问题,您只需要定义bgColor
for 循环的内部,因此对于列表中的每个项目,它都定义了一个具有不同引用的新对象。
for (document in result) {
var bgColor: Int = 0
....
推荐阅读
- wpf - WPF DataGrid 生成名称不正确的列
- php - PHP 排序多维数组 - array_multisort 给出错误
- python-3.x - 使用 XGboost 预测测试和训练时的特征名称不匹配
- excel - 在高级过滤器中包含一个计数器
- xml - 如何拆分串联的 XML 文档?
- php - 当包含多个文件时,返回一个数组,我将第一个包含的数组合并到第二个包含中,为什么?
- linux - 如何在 cmake 命令中回显 shebang
- java - JNI目录结构c和java
- angular - 将引导文件导入组件时出现编译错误
- c# - 如何将上传的文件存储到 MySQL LONGBLOB 列中并再次查看上传的文件?