I am creating an app for my students. I am a teacher and hobby developer. Therefore, I need help. With three fragments, I successively create the name of the class, and the data of the student(first Name, last Name,..) then I attribute evaluation data to him. Everything works correctly. Except when I post all my students in the class in different groups. I end up with a student of the same name each time I validate the assessment for a new student. So over time, I'm going to end up with the same student 30 times in this display. I don't understand where the problem comes from. thank you for guiding me.
here is my code to add a student:
class AddFragment : androidx.fragment.app.Fragment() {
private lateinit var mUserViewModel: UserViewModel
private lateinit var mEvalViewModel : EvalViewModel
private lateinit var mUserEvalViewModel: UserEvalViewModel
private val args by navArgs<AddFragmentArgs>()
//Pour accéder au fab
private var _binding: FragmentAddBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
_binding = FragmentAddBinding.inflate(inflater, container,false)
val view = binding.root
mUserViewModel = ViewModelProvider(this).get(UserViewModel::class.java)
mEvalViewModel = ViewModelProvider(this).get(EvalViewModel::class.java)
mUserEvalViewModel = ViewModelProvider(this).get(UserEvalViewModel::class.java)
binding.addNameGroupEt.setText(args.currentGru.nameGroupG)
binding.btnAddFragmentAdd.setOnClickListener {
insertDataToDatabase()
soundClic()
}
return view
}
private fun insertDataToDatabase() {
val idUser = 0
val firstName = binding.addFirstNameEt.text.toString()
val lastName = binding.addLastNameEt.text.toString()
val nbTeam = binding.addNumberTeamEt.text.toString()
val gru_id_reference = args.currentGru.idGroup
if(inputCheck(firstName, lastName, nbTeam)){
//Create User OBject
val user = User(idUser, args.currentGru.nameGroupG, firstName, lastName, nbTeam, gru_id_reference)
//Add Data to Database
mUserViewModel.addUser(user)
val action = AddFragmentDirections.actionAddFragmentToAddEvalFragment(user)
findNavController().navigate(action)
Toast.makeText(requireContext(), "Ajout réussi !", Toast.LENGTH_SHORT).show()
}else{
Toast.makeText(requireContext(), "Veuillez remplir tous les champs, SVP !", Toast.LENGTH_LONG).show()
}
}
private fun inputCheck(firstName: String, lastName: String, nbTeam: String): Boolean{
return !( TextUtils.isEmpty(firstName) && TextUtils.isEmpty(lastName) && TextUtils.isEmpty(nbTeam))
}
private fun soundClic() {
val mediaPlayer: MediaPlayer = MediaPlayer.create(context, R.raw.select_click)
mediaPlayer.start()
}
}
Then i arrive on my code to add Evaluation for my student:
here the code to addEvalFragment:
class AddEvalFragment : androidx.fragment.app.Fragment() {
private lateinit var mUserViewModel: UserViewModel
private lateinit var mEvalViewModel : EvalViewModel
private lateinit var mUserEvalViewModel: UserEvalViewModel
private val args by navArgs<AddEvalFragmentArgs>()
private var _binding: FragmentAddEvalBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
_binding = FragmentAddEvalBinding.inflate(inflater, container,false)
val view = binding.root
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val adapter = AddEvalAdapter()
val recyclerView = view.findViewById<RecyclerView>(R.id.recyclerview)
recyclerView?.adapter = adapter
recyclerView?.layoutManager = LinearLayoutManager(requireContext())
mUserViewModel = ViewModelProvider(this).get(UserViewModel::class.java)
mEvalViewModel = ViewModelProvider(this).get(EvalViewModel::class.java)
mUserEvalViewModel = ViewModelProvider(this).get(UserEvalViewModel::class.java)
mUserViewModel.getOneUser(args.currentUser.firstName, args.currentUser.lastName, args.currentUser.nameGroup)?.observe(viewLifecycleOwner, Observer {
user ->
user.let {
adapter.setDataOneUser(user)
}
})
}
}
and the code of my addEvalAdapter:
class AddEvalAdapter: RecyclerView.Adapter<AddEvalAdapter.MyViewHolder>() {
private lateinit var context: Context
var userList = emptyList<User>()
class MyViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) { }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
context = parent.context
return MyViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.custom_row_add_eval, parent, false))
}
override fun getItemCount(): Int {
return userList.size
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val currentItem = userList[position]
holder.itemView.findViewById<TextView>(R.id.firstName_txt_Add_Eval).text = currentItem.firstName
holder.itemView.findViewById<TextView>(R.id.lastName_txt_Add_Eval).text = currentItem.lastName
holder.itemView.findViewById<TextView>(R.id.numeroTeam_txt_Add_Eval).text = currentItem.nbTeam
holder.itemView.findViewById<Button>(R.id.btn_start_eval_Add_Eval).setOnClickListener {
val eval = Eval(
idEval = currentItem.id, note_seize = "0", note_douze = "0",
note_relation = "0", note_trajets = "0", note_moteur = "0", note_emotion = "0", note_afl2 = "0", note_afl3 = "0",
note_sur_vingt = "0", user_id_reference = currentItem.id)
EvalViewModel(application = Application()).addEval(eval)
Toast.makeText(context, "Bravo !", Toast.LENGTH_SHORT).show()
soundClic()
val action =
AddEvalFragmentDirections.actionAddEvalFragmentToListMultipleTeam(Gru(currentItem.gru_id_reference, currentItem.nameGroup))
holder.itemView.findNavController().navigate(action)
soundClic()
}
}
private fun soundClic() {
val mediaPlayer: MediaPlayer = MediaPlayer.create(context, R.raw.select_click)
mediaPlayer.start()
}
fun setDataOneUser(user: List<User>){
this.userList = user
notifyDataSetChanged()
}
}
And my code to display the students. It's here who see multiple of the same student.
Here the code:
class MultipleAdapter: RecyclerView.Adapter<MultipleAdapter.MyViewHolder>() {
var userList = emptyList<User>()
private lateinit var context: Context
class MyViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) { }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
context = parent.context
return MyViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.custom_row_multiple, parent, false))
}
override fun getItemCount(): Int {
return userList.size
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val currentItem = userList[position]
holder.itemView.findViewById<Button>(R.id.btn_start_eval_multiple).isVisible = true
holder.itemView.findViewById<TextView>(R.id.firstName_txt_multiple).text = currentItem.firstName
holder.itemView.findViewById<TextView>(R.id.lastName_txt_multiple).text = currentItem.lastName
holder.itemView.findViewById<Button>(R.id.btn_start_eval_multiple).setOnClickListener {
val action = MultipleFragmentDirections.actionMultipleFragmentToEvalFragment(User(currentItem.id, currentItem.nameGroup, currentItem.firstName, currentItem.lastName, currentItem.nbTeam, currentItem.gru_id_reference))
holder.itemView.findNavController().navigate(action)
soundClic()
}
}
private fun soundClic() {
val mediaPlayer: MediaPlayer = MediaPlayer.create(context, R.raw.select_click)
mediaPlayer.start()
}
fun setDataMultiple(user: List<User>){
this.userList = user
notifyDataSetChanged()
}
}
Here my query of to display my student on the multiplefragment:
@Query("SELECT * FROM user_table JOIN eval_table WHERE gru_id_reference LIKE :gru_id AND nbTeam LIKE :nbTeam ORDER BY lastName ASC")
fun retrieveUserWithNameGroup( gru_id: Int, nbTeam: String): LiveData<List<User>>
I don't understand where the problem comes from.
I believe that your issue is that the query SELECT * FROM user_table JOIN eval_table WHERE gru_id_reference LIKE :gru_id AND nbTeam LIKE :nbTeam ORDER BY lastName ASC
will result in the cartesian product, that is a row for every combination of user and eval.
So if user X has 10 evals then there will be 10 rows and hence 10 of that User in the List and so on.