如何使用分页库在RecyclerView中显示列表数组中的每个项目



大家早上好,我希望你们做得很好。我正在使用带有两个表或实体的Room数据库,并希望使用分页库在回收器视图中显示学生学习的所有课程的列表。在适配器的bind((方法中,当我在数据库中保存了四门课程后第一次使用binding.courseName.text = studentCourse.courses.courseName.toString()查看输出以及学习过这些课程的学生的姓名时,它返回一个数组,如下所示:

**[课程(courseName=Android,courseDuration=50(,课程(couseName=Python,couseDuration=40

使用下面的代码,它在recyclerator视图中只返回一个带有名称和持续时间的课程,这是数组的最后一个课程。

CourseStudent这两个表或实体的定义如下:

@Entity(tableName = "course_table")
data class Course(
@PrimaryKey(autoGenerate = false)
val courseName : String,
@ColumnInfo(name = "course_duration")
val courseDuration : String
)
@Entity(tableName = "student_table")
data class Student(
@PrimaryKey(autoGenerate = false)
val studentName : String,
val semester : Int,
val schoolName : String
)

这两个类之间的关系由StudentAndCourse和CourseAndStudent**类表示,定义如下:

data class StudentAndCourse(
@Embedded
val student : Student,
@Relation(
parentColumn = "studentName",
entityColumn = "courseName",
associateBy = Junction(StudentAndCourseTogether::class)
)
val courses : List<Course>
)
data class CourseAndStudent(
@Embedded
val course : Course,
@Relation(
parentColumn = "courseName",
entityColumn = "studentName",
associateBy = Junction(StudentAndCourseTogether::class)
)
val students : List<Student>
)

我在Dao中定义的查询是:

@Query("SELECT * FROM student_table WHERE studentName = :studentName")
fun getAllCoursesByStudentName(studentName: String) : PagingSource<Int, StudentAndCourse>```

Here is my Paging Adapter class:

class CourseByStudentNameAdapter:寻呼数据适配器<学生和课程,CourseByStudentNameAdapter.CourseByStudentNameViewHolder>(DiffCallback({

class CourseByStudentNameViewHolder(private val binding: CourseByStudentNameItemBinding) :
RecyclerView.ViewHolder(binding.root){
fun bind(studentAndCourse: StudentAndCourse){
for (course in studentAndCourse.courses){
binding.courseName.text = course.courseName
binding.courseDuration.text = course.courseDuration
}
}
}
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int,
): CourseByStudentNameAdapter.CourseByStudentNameViewHolder {
val inflatedLayout = CourseByStudentNameItemBinding.inflate(LayoutInflater.from(
parent.context), parent, false)
return CourseByStudentNameViewHolder(inflatedLayout)
}

override fun onBindViewHolder(holder: CourseByStudentNameAdapter.CourseByStudentNameViewHolder, position: Int) {
val currentCourse = getItem(position)
if (currentCourse != null) {
holder.bind(currentCourse)
}
}

companion object DiffCallback : DiffUtil.ItemCallback<StudentAndCourse>(){
override fun areItemsTheSame(
oldItem: StudentAndCourse,
newItem: StudentAndCourse
): Boolean = oldItem.courses == newItem.courses
override fun areContentsTheSame(
oldItem: StudentAndCourse,
newItem: StudentAndCourse
): Boolean = oldItem == newItem
}

}```

保存项目的XML文件:

<androidx.constraintlayout.widget.ConstraintLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/linear_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:layout_marginTop="4dp"
style="@style/itemListTextStyle"
android:background="@drawable/item_layout_background"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<TextView
android:id="@+id/course_name"
android:layout_width="match_parent"
tools:text="Computer"
android:gravity="center"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/course_duration"
android:layout_width="match_parent"
tools:text="15 hours"
android:gravity="center"
android:layout_height="wrap_content"/>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>```

My fragment code:
```
@AndroidEntryPoint
class AllCourseByStudentNameFragment : Fragment() {
private var _binding : FragmentAllCourseByStudentNameBinding? = null
private val binding get() = _binding!!
private val viewModel : SchoolViewModel by activityViewModels()
private lateinit var adapter : CourseByStudentNameAdapter
private val schoolName = "IFRI"
private val studentName = "Esperant"
private val courseName = "Android"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}

override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?,
): View? {
// Inflate the layout for this fragment
_binding = FragmentAllCourseByStudentNameBinding.inflate(inflater)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
adapter = CourseByStudentNameAdapter()
binding.apply {
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(requireContext())
recyclerView.setHasFixedSize(true)
}
viewModel.setName(studentName)
viewModel.courseByStudentName.observe(viewLifecycleOwner){
adapter.submitData(viewLifecycleOwner.lifecycle, it)
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}```
I will be very glad to get your help. Thanks in advance.


问题将出现在ViewHolder中。ViewHolder代表RecyclerView中的单个项目,而不是全部项目。

实现方式:

class CourseByStudentNameViewHolder(private val binding: CourseByStudentNameItemBinding) :
RecyclerView.ViewHolder(binding.root){
fun bind(studentAndCourse: StudentAndCourse){
for (course in studentAndCourse.courses){
binding.courseName.text = course.courseName
binding.courseDuration.text = course.courseDuration
}
}
}

当您通过StudentAndCourse项目(这是一个单独的项目(时,适配器会认为只有一个项目可以显示。您的ViewHolder应用于绑定单个RecyclerView项目(课程(的数据。你实现它的方式是,你在所有课程上循环,对于每个循环,你都会再次覆盖courseName和courseDuration。因此,最终只有最后一个课程的值才可见,因为之前的所有课程都被覆盖了。

不要在适配器中使用StudentAndCourse,而是尝试为StudentAnd课程对象中的每个课程传递一个单独的课程,这样适配器就知道列表中有不止一个项目。

class CourseByStudentNameAdapter : PagingDataAdapter<Course, CourseByStudentNameAdapter.CourseByStudentNameViewHolder>(DiffCallback) {
class CourseByStudentNameViewHolder(private val binding: CourseByStudentNameItemBinding) : RecyclerView.ViewHolder(binding.root){

fun bind(course: Course){
binding.courseName.text = course.courseName
binding.courseDuration.text = course.courseDuration
}
}
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int,
): CourseByStudentNameAdapter.CourseByStudentNameViewHolder {
val inflatedLayout = CourseByStudentNameItemBinding.inflate(LayoutInflater.from(
parent.context), parent, false)
return CourseByStudentNameViewHolder(inflatedLayout)
}

override fun onBindViewHolder(holder: CourseByStudentNameAdapter.CourseByStudentNameViewHolder, position: Int) {
val currentCourse = getItem(position)
if (currentCourse != null) {
holder.bind(currentCourse)
}
}

companion object DiffCallback : DiffUtil.ItemCallback<Course>(){
override fun areItemsTheSame(
oldItem: Course,
newItem: Course
): Boolean = oldItem.courseName == newItem.courseName
override fun areContentsTheSame(
oldItem: Course,
newItem: Course
): Boolean = oldItem == newItem
}
}

您可以查看页面数据的官方文档:文档

最新更新