0

So i have this strange behaviour where my RecyclerView only Displays data when i start the App and then restart the activity via Android Studio. Or make a change in XML, then undo it and restart. The then displayed data is correct and also updates when i add things, but it is not visible after starting the app.

Can anyone help me out? I am really clueless why that would be.

Fragment:

@AndroidEntryPoint
class HistoryFragment : Fragment(R.layout.fragment_history) {

    private val viewModel: PurchaseViewmodel by viewModels()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val binding = FragmentHistoryBinding.bind(view)

        val exampleAdapter = ExampleAdapter()

        binding.apply{
            recyclerView.apply{

                layoutManager = LinearLayoutManager(requireContext())
                adapter = exampleAdapter
                setHasFixedSize(true)
            }
            ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) {
                override fun onMove(
                    recyclerView: RecyclerView,
                    viewHolder: RecyclerView.ViewHolder,
                    target: RecyclerView.ViewHolder
                ): Boolean {
                    return false /// We dont need any interaction with Drag&Drop we only want swipe left&right
                }

                override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
                    val receipt = exampleAdapter.currentList[viewHolder.adapterPosition]
                     viewModel.onSwipe(receipt)
                }
            }).attachToRecyclerView(recyclerView)
        }

        setFragmentResultListener("add_receipt_request"){_,bundle ->
            val result = bundle.getInt("add_receipt_request")
            viewModel.onAddResult(result)
        }

        viewModel.receipts.observe(viewLifecycleOwner){ /// New Items get passed to the List
            exampleAdapter.submitList(it)
        }
        viewLifecycleOwner.lifecycleScope.launchWhenStarted { //as soon as we close our app the events will be suspended, but not deleted and will remain after restart
            viewModel.addTaskEvent.collect {  event->
                when(event){
                    is PurchaseViewmodel.TasksEvent.ShowUndoDelete -> {
                        Snackbar.make(requireView(),"Tasks deleted", Snackbar.LENGTH_LONG)
                            .setAction("UNDO"){
                                viewModel.unDoDeleteClick(event.receipts)
                            }.show()
                    }
                }
            }
        }

    }
}

Adapter:

class ExampleAdapter : ListAdapter<Receipts,ExampleAdapter.ExampleViewHolder>(DiffCallback()) {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ExampleViewHolder { 
        val binding = ReceiptsBinding.inflate(LayoutInflater.from(parent.context),parent,false)
        return ExampleViewHolder(binding)
    }

    override fun onBindViewHolder(holder: ExampleViewHolder, position: Int) {
        val currentItem = getItem(position)
        holder.bind(currentItem)
    }

    override fun getItemCount(): Int {
        return super.getItemCount()
    }

    class ExampleViewHolder(private val binding: ReceiptsBinding) : RecyclerView.ViewHolder(binding.root){ //Examples One Row in our list
        fun bind (receipts: Receipts) {
            binding.apply {
                storeHistory.text = receipts.store
                amountHistory.text = receipts.total
                dateHistory.text  = receipts.date
            }
        }
    }


    class DiffCallback : DiffUtil.ItemCallback<Receipts>() {
        override fun areItemsTheSame(oldItem: Receipts, newItem: Receipts) =
            oldItem.id == newItem.id


        override fun areContentsTheSame(oldItem: Receipts, newItem: Receipts) =
            oldItem == newItem
    }
}
Zain
  • 37,492
  • 7
  • 60
  • 84
dkiwikid
  • 95
  • 1
  • 9
  • Are you calling `notifyDataSetChanged()` or `notifyItemChanged()` on the adapter anywhere? I don't see it in the code you posted. Those methods tell the adapter to update the view when elements are added or removed. – Yirmi Jun 17 '21 at 21:19
  • I don't, but my problem is not that the list doesnt show when data is updated, but when i initially start the app. – dkiwikid Jun 17 '21 at 21:22
  • 1
    What is that `binding` object creation in `onViewCreated`? In fact, fragments have a function called `onCreateView` which is the place you instantiate the binding and store it in a property in fragment and return `binding.root` and inside `onViewCreated` you will use that property. Creating a new binding in `onViewCreated` is just creating a useless object, doing some operations on it, and toss it away. It would be helpful of you add your `onCreateView` as well – Amin Jun 17 '21 at 21:46
  • Thank you! But I am not sure how to implement your idea. What do I have to put into the onViewCreated and what in onCreate? – dkiwikid Jun 18 '21 at 16:45

1 Answers1

0

You should compare corresponding fields of old/new Receipts in areContentsTheSame() instead of comparing the entire old/new objects

override fun areContentsTheSame(oldItem: Receipts, newItem: Receipts) = 
    oldItem.store == newItem.store 
            && oldItem.total == newItem.total 
            && oldItem.date == newItem.date
Zain
  • 37,492
  • 7
  • 60
  • 84