I'm seaching solution for this since five days. I'm one of GADS 2021 scholars and have Google Android Developer Certification exam in few days, this month. I'm working on a small project that includes Room Database with four tables and there're two tables Student and Course with N to N relationship. My goal is to to search a student by his name and display all the courses taken by this one in a recycler view using ListAdapter or Paging library but with my code, it doesn't work and I don't know the reason. So I'm looking for a way to do that.I know if I find a solution for this, I can use it for other parts of the project. I really need help for this. I want to use it in an other app I want to publish on PlayStore, that app will be my first app. Here is what I did in the project I'm working with:
MY TWO TABLES OR ENTITIES:
@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
)
RELATIONS BETWEEN TABLES
@Entity(primaryKeys = ["studentName", "courseName"])
data class StudentAndCourseTogether(
val studentName : String,
val courseName : String
)
data class CourseAndStudent(
@Embedded
val course : Course,
@Relation(
parentColumn = "courseName",
entityColumn = "studentName",
associateBy = Junction(StudentAndCourseTogether::class)
)
val students : List<Student>
)
data class StudentAndCourse(
@Embedded
val student : Student,
@Relation(parentColumn = "studentName", entityColumn = "courseName", associateBy = Junction(StudentAndCourseTogether::class))
val courses : List<Course>
)
MY QUERY TO GET ALL COURSES TAKEN BY A STUDENT
@Transaction
@Query("SELECT * FROM student_table WHERE studentName = :studentName")
fun getAllCoursesByStudentName(studentName: String) : Flow<List<StudentAndCourse>>
MY REPOSITORY CODE
val allCourseByStudentName = allItemsByNameDao.getAllCoursesByStudentName(studentName = "Esperant")
MY VIEWMODEL CODE
val coursesByStudentName : LiveData<List<StudentAndCourse>> = allItemsByNameRepository.allCourseByStudentName.asLiveData()
MY ADAPTER CODE
class CourseByStudentNameAdapter :
ListAdapter<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,
): CourseByStudentNameViewHolder {
val inflatedLayout = CourseByStudentNameItemBinding.inflate(LayoutInflater.from(
parent.context), parent, false)
return CourseByStudentNameViewHolder(inflatedLayout)
}
override fun onBindViewHolder(holder: 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
}
}
MY ASSOCIETED FRAGMENT CODE
@AndroidEntryPoint
class AllCourseByStudentNameFragment : Fragment() {
private var _binding : FragmentAllCourseByStudentNameBinding? = null
private val binding get() = _binding!!
private val viewModel : AllItemsByNameViewModel by activityViewModels()
private lateinit var adapter : CourseByStudentNameAdapter
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
}
@SuppressLint("LongLogTag")
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(enteredName = "Esperant")
viewModel.coursesByStudentName.observe(viewLifecycleOwner){
for (course in it){
adapter.submitList(course.courses)
}
Log.d(TAG, "The returned list size is ${it.size}")
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
I'm seaching solution for this since five days. I'm one of GADS 2021 scholars and have Google Android Developer Certification exam in few days, this month. I'm working on a small project that includes Room Database with four tables and there're two tables Student and Course with N to N relationship. My goal is to to search a student by his name and display all the courses taken by this one in a recycler view using ListAdapter or Paging library but with my code, it doesn't work and I don't know the reason. So I'm looking for a way to do that.I know if I find a solution for this, I can use it for other parts of the project. I really need help for this. I want to use it in an other app I want to publish on PlayStore, that app will be my first app. Here is what I did in the project I'm working with:
MY TWO TABLES OR ENTITIES:
RELATIONS BETWEEN TABLES
MY QUERY TO GET ALL COURSES TAKEN BY A STUDENT
MY REPOSITORY CODE
MY VIEWMODEL CODE
MY ADAPTER CODE
MY ASSOCIETED FRAGMENT CODE
MY XML CODE
The project repository link
https://github.com/esperantgada/Room_With_Multiple_Tables
I'll be very glad to hear from you, it's very important for me. Thanks in advance