Abdul
Abdul

Reputation: 57

Pass items from recycleView to another recycleView in Kotlin

I am newbie Kotlin programmer. I used Notes tutorial to create a recycle view with add button.

In this tutorial he used MVVM pattern design. (model,ViewModel,Repository, and Firebse) NavGraph also used.

My Goal of this app is to start my own application, which is to have a list of players name and info on each item list on the recycle view with a buttons to determine if players came on time or late

so, I need to have a fragment for late players list (which has another recycleView) to show items when late button clicked.

What I have so far, I am able to create a players list "note" and can be deleted, edited but I need when late button clicked send the item to late players fragment with username and time when the button clicked

I have tried to create a data class for late players (usename, id, date). I tried to bind data from the main layout to late players layout but I failed ...

please guide me how to fix my issue

Please find source code for the whole app here on this link https://github.com/abdoh77/MTeamApp

This is what i have now and I need to get to pass data from Players list to another fragment with recycle view

Here is the Data model

package com.example.mteam.data.model

import android.os.Parcelable
import com.google.firebase.firestore.ServerTimestamp
import kotlinx.parcelize.Parcelize
import java.util.Date

@Parcelize
data class PlayersNote (
var id: String = "",
val username: String ="",
val mobile: String="",

@ServerTimestamp
val date: Date = Date(),

):Parcelable

This is the utility

     package com.example.mteam.util

 sealed class UiState <out  T>{
 //loading, success, failure
 object Loading: UiState<Nothing>()
 //we will show the progress bar only
 data class Success<out T>(val data: T): UiState<T>() 
 // On Success we will return data (T) Generic "anyType"
  data class Failure(val error: String?): UiState<Nothing>() 
  // String  to indicate failure message
  }

Here is Repository class

package com.example.mteam.data.repository

import com.example.mteam.data.model.PlayersNote
import com.example.mteam.util.FireStoreTables
import com.example.mteam.util.UiState
import com.google.firebase.firestore.FirebaseFirestore

class PlayersNoteRepositoryImp(
val database: FirebaseFirestore   
 //Repository depending on Firebase to get the data.
): PlayersNoteRepository {

//we will get data from firebase collection
override fun getNotes(result: (UiState<List<PlayersNote>>) -> Unit){
database.collection(FireStoreTables.NOTE)
        .get()
        .addOnSuccessListener {
            val notes = arrayListOf<PlayersNote>()
            for (document in it){  
             //convert the document into model class
                val note = document.toObject(PlayersNote::class.java)
            // convert the document to this model class
                notes.add(note) // add model class into the playersNote 
          list
            }
            result.invoke(
                UiState.Success(notes)
            )
        }
        .addOnFailureListener {
            result.invoke(
                UiState.Failure(
                    it.localizedMessage
                )
            )
        }
}

override fun addNote(note: PlayersNote, result: (UiState<String>) -> Unit) {
    val document = database.collection(FireStoreTables.NOTE).document()
    note.id = document.id

   document
        .set(note)
        .addOnSuccessListener {
            result.invoke(
                UiState.Success("Created successfully")

            )
        }
        .addOnFailureListener {
            result.invoke(
                UiState.Failure(
                    it.localizedMessage
                )
            )

        }
}


override fun updateNote(note: PlayersNote, result: (UiState<String>) -> Unit) {
    val document = database.collection(FireStoreTables.NOTE).document(note.id)
    document
        .set(note)
        .addOnSuccessListener {
            result.invoke(
                UiState.Success("Note updated successfully")

            )
        }
        .addOnFailureListener {
            result.invoke(
                UiState.Failure(
                    it.localizedMessage
                )
            )

        }
}

override fun deleteNote(note: PlayersNote, result: (UiState<String>) -> Unit) {
    val document = database.collection(FireStoreTables.NOTE).document(note.id)
    document
        .delete()
        .addOnSuccessListener {
            result.invoke(
                UiState.Success("Note Deleted successfully")

            )
        }
        .addOnFailureListener {
            result.invoke(
                UiState.Failure(
                    it.localizedMessage
                )
            )

        }
}
}

Here is my Adapter

package com.example.mteam.note


import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.mteam.data.model.PlayersNote
import com.example.mteam.databinding.ItemsPlayersListBinding

class NoteListingAdapter(
val onItemClicked: (Int, PlayersNote) -> Unit,
val onEditClicked: (Int, PlayersNote) -> Unit,
val onDeleteClicked: (Int, PlayersNote) -> Unit
) : RecyclerView.Adapter<NoteListingAdapter.MyViewHolder>() {

private var list: MutableList<PlayersNote> = arrayListOf()

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
    val itemView = ItemsPlayersListBinding.inflate(LayoutInflater.from(parent.context),parent,false)
    return MyViewHolder(itemView)
}

override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
    val item = list[position]
    holder.bind(item)
}

fun updateList(list: MutableList<PlayersNote>){
    this.list = list
    notifyDataSetChanged()
}

fun removeItem(position: Int){
    list.removeAt(position)
    notifyItemChanged(position)
}

override fun getItemCount(): Int {
    return list.size
}

inner class MyViewHolder(val binding: ItemsPlayersListBinding) : 
 RecyclerView.ViewHolder(binding.root) {
    fun bind(item: PlayersNote){
        // binding.id.setText(item.id)
        binding.mTitle.setText(item.username)
        binding.mSubTitle.setText(item.mobile)
        binding.edit.setOnClickListener { 
onEditClicked.invoke(bindingAdapterPosition,item) }
        binding.delete.setOnClickListener { 
onDeleteClicked.invoke(bindingAdapterPosition,item) }
        binding.itemLayout.setOnClickListener { 
onItemClicked.invoke(bindingAdapterPosition,item) }
    }
}
}

Here is the Player list activity code

package com.example.mteam.note

import android.nfc.Tag
import android.os.Bundle
import android.provider.Settings.Global.putString
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import com.example.mteam.R
import com.example.mteam.data.model.PlayersNote
import com.example.mteam.databinding.FragmentNotePlayersListBinding
import com.example.mteam.util.UiState
import com.example.mteam.util.hide
 import com.example.mteam.util.show
import com.example.mteam.util.toast
import com.google.android.material.tabs.TabLayout.TabGravity
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class NotePlayersList : Fragment() {

val TAG: String = "NotePlayersList"
lateinit var binding : FragmentNotePlayersListBinding
val viewModel: PlayersNoteViewModel by viewModels()  // instance of 
viewModel to get the data to the fragment
var deletePosition: Int = -1
var list: MutableList<PlayersNote> = arrayListOf()
val adapter by lazy {
    NoteListingAdapter(
        onItemClicked = { pos, item ->
            findNavController().navigate( 
     R.id.action_notePlayersList_to_notePlayersDetails,Bundle().apply {
                    putString("type","view")
                    putParcelable("note",item)
                })

        },
        onEditClicked = {pos, item ->

            findNavController().navigate( 
       R.id.action_notePlayersList_to_notePlayersDetails,Bundle().apply 
           {
                putString("type","edit")
                putParcelable("note",item)
            })
        },
        onDeleteClicked = { pos, item ->
            deletePosition = pos
            viewModel.deleteNote(item)

        }
    )

}


override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    binding = FragmentNotePlayersListBinding.inflate(layoutInflater)
    return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    binding.recyclerView.adapter = adapter
    binding.recyclerView.itemAnimator = null
    binding.createButton.setOnClickListener{
        








  findNavController().navigate( 
   R.id.action_notePlayersList_to_notePlayersDetails,Bundle().apply {
            putString("type","create")
        })

    }
    viewModel.getNotes() //we are calling this function from the ViewModel
    viewModel.note.observe(viewLifecycleOwner){
        //This is how we got data from live data inside fragment

        when(it){

            is UiState.Loading -> {
                binding.progressBar.show()
                //Log.e(TAG,"Loading")
            }
            is UiState.Failure -> {
                binding.progressBar.hide()
                toast(it.error)
            //Log.e(TAG,it.error. toString())

            }
            is UiState.Success -> {
                binding.progressBar.hide()
                list = it.data.toMutableList()
                adapter.updateList(list)

            }


        }


        }

    viewModel.deleteNote.observe(viewLifecycleOwner){
        //This is how we got data from live data inside fragment

        when(it){

            is UiState.Loading -> {
                binding.progressBar.show()
                //Log.e(TAG,"Loading")
            }
            is UiState.Failure -> {
                binding.progressBar.hide()
                toast(it.error)
           // Log.e(TAG,it.error. toString())

            }
            is UiState.Success -> {
                binding.progressBar.hide()
                toast(it.data)
                if (deletePosition != -1) {
                    list.removeAt(deletePosition)
                    adapter.updateList(list)
                }
            }


        }


    }

    }
}

This is the ViewModel

package com.example.mteam.note


import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.example.mteam.data.model.PlayersNote
import com.example.mteam.data.repository.PlayersNoteRepository
import com.example.mteam.util.UiState
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject


@HiltViewModel
class PlayersNoteViewModel @Inject constructor(
val repository: PlayersNoteRepository //Dependency of Repository
): ViewModel() {

//To pass data from view model to fragment or activity we use 
livedata
private val _notes = MutableLiveData<UiState<List<PlayersNote>>>()
val note: LiveData<UiState<List<PlayersNote>>>
    get() = _notes

// to add note
private val _addNote = MutableLiveData< UiState<String>>()
val addNote: LiveData<UiState<String>> //we used String because we are going to pass doucments ID
    get() = _addNote

// to update note
private val _updateNote = MutableLiveData< UiState<String>>()
val updateNote: LiveData<UiState<String>> //we used String because we are going to pass doucments ID
    get() = _updateNote

// to delete note
private val _deleteNote = MutableLiveData< UiState<String>>()
val deleteNote: LiveData<UiState<String>> //we used String because we are going to pass doucments ID
    get() = _deleteNote

fun getNotes() {
    _notes.value = UiState.Loading
    repository.getNotes {
        _notes.value = it
    }
}

fun addNote(note: PlayersNote){ //will pass the note object
    _addNote.value =UiState.Loading // to trger the loading state
    repository.addNote(note){ //getting the note from repository
        _addNote.value = it
    }

}

fun updateNote(note: PlayersNote){ //will pass the note object
    _updateNote.value =UiState.Loading // to trger the loading state
    repository.updateNote(note){ //getting the note from repository
        _updateNote.value = it
    }

}

fun deleteNote(note: PlayersNote) {
    _deleteNote.value =UiState.Loading // to trger the loading state
    repository.deleteNote(note){ //getting the note from repository
        _deleteNote.value = it
    }
}


}

Thank you

enter image description here

enter image description here

Upvotes: 0

Views: 35

Answers (0)

Related Questions