Search code examples
androidfirebasekotlinandroid-recyclerviewnotifydatasetchanged

RecyclerView, display repeated items when rotating the screen or changing fragments


I am making an application in Android Studio in Kotlin with fragments synchronized with the Faribase platform, in which a RecyclerView and Adapter are made in a fragment to be a list of web pages, everything works fine, but when I turn the cell phone from vertical to horizontal or when I leave the fragment and go back, the elements are duplicated. I don't know what the error is, if you can help me, I think the error is in the Adapter.


class ShareFragment : Fragment() {

    private lateinit var shareBinding: FragmentShareBinding
    private lateinit var shareViewModel: ShareViewModel
    private lateinit var shareAdapter: ShareAdapter
    private var shareVehicle: ArrayList<PaperworkServer> = ArrayList()

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        shareBinding = FragmentShareBinding.inflate(inflater, container, false)
        shareViewModel = ViewModelProvider(this)[ShareViewModel::class.java]
        return shareBinding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        shareViewModel.loadShareFromServerDone.observe(viewLifecycleOwner) { result ->
            onLoadChareFromServerDoneSubscribe(result)
        }

        shareViewModel.loadPaperworkServer()
        shareAdapter = ShareAdapter(shareVehicle, onItemClicked = { onShareItemClicked(it) })
        shareBinding.shareView.apply {
            layoutManager = LinearLayoutManager([email protected]())
            adapter = shareAdapter
            setHasFixedSize(false)
        }
    }

    private fun onShareItemClicked(share: PaperworkServer) {
        findNavController().navigate(ShareFragmentDirections.actionShareFragmentToLinkTwoFragment(share))
    }

    private fun onLoadChareFromServerDoneSubscribe(shareServerLoaded: ArrayList<PaperworkServer>) {
        shareVehicle = shareServerLoaded
        shareAdapter.appendItems(shareVehicle)
    }
}

Adapter

class ShareAdapter(
    private val shareList: ArrayList<PaperworkServer>,
    private val onItemClicked: (PaperworkServer) -> Unit
) : RecyclerView.Adapter<ShareAdapter.ShareViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ShareViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.card_view_item_share, parent, false)
        return ShareViewHolder(view)
    }

    override fun onBindViewHolder(holder: ShareViewHolder, position: Int) {
        val share = shareList[position]
        holder.bind(share)
        holder.itemView.setOnClickListener{ onItemClicked(shareList[position])}
    }

    override fun getItemCount(): Int = shareList.size

    fun appendItems(newList: ArrayList<PaperworkServer>){
        shareList.clear()
        shareList.addAll(newList)
        notifyDataSetChanged()
    }

    class ShareViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
        private val binding = CardViewItemShareBinding.bind(itemView)
        fun bind(share: PaperworkServer){
            with(binding){
                titleLinkTextView.text = share.name
                cardShareTextView.text = share.information
            }
        }
    }
}

ViewModel

class ShareViewModel : ViewModel() {

    val paperworkServerRepository = PaperworkServerRepository ()
    private var shareVehicle: ArrayList<PaperworkServer> = ArrayList()

    val loadPaperworkServer: MutableLiveData<ArrayList<PaperworkServer>> = MutableLiveData()
    val loadShareFromServerDone: LiveData<ArrayList<PaperworkServer>> = loadPaperworkServer

    fun loadPaperworkServer (){
        GlobalScope.launch(Dispatchers.IO){
            val querySnapshot = paperworkServerRepository.share()
            for (document in querySnapshot) {
                val paperworkServer: PaperworkServer = document.toObject<PaperworkServer>()
                shareVehicle.add(paperworkServer)
            }
            loadPaperworkServer.postValue(shareVehicle)
        }
    }
}

screenshot of operation

enter image description here

Error when rotating the screen or moving from fragment to fragment, elements are duplicated

enter image description here

I have tried modifying the adapter but without results. Also, the notifyDataSetChanged() method does not work.


Solution

  • To handle screen rotation check the savedInstanceState and add this code inside the block

    if (savedInstanceState == null) {
        shareViewModel.loadPaperworkServer()
        shareAdapter = ShareAdapter(shareVehicle, onItemClicked = { onShareItemClicked(it) })
        shareBinding.shareView.apply {
            layoutManager = LinearLayoutManager([email protected]())
            adapter = shareAdapter
            setHasFixedSize(false)
          }
       }