Search code examples
androidkotlinandroid-recyclerviewnotifydatasetchangednotifyitemchanged

Has anyone got notifyDataSetChanged() working in Kotlin?


I have a RecyclerView which displays a list of short phrases read from the MutableList modSamplePhrases. When an item is tapped, a DialogFragment pops up which shows the phrase from the list item and allows it to be edited. When the edit is completed, the new text is returned to the RecyclerFragment via the function getDataFromDialog(). Logcat shows that the underlying data updates successfully (so .clear() & .addAll() make no difference) but still the call to notifyItemChanged(pos) or notifyDataSetChanged() simply does nothing.

class PhraseRecyclerFragment : Fragment(){

    private var modSamplePhrases = PhraseData().samplePhrases

    private var phraseListAdapter = PhraseListAdapter(modSamplePhrases)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        retainInstance = true
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? =
        inflater.inflate(R.layout.fragment_recycler, container, false)

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
       list_recycler_view.apply {
            layoutManager = LinearLayoutManager(activity)
            adapter = phraseListAdapter
        }

        list_recycler_view.addOnItemClickListener(object: OnItemClickListener {
            override fun onItemClicked(position: Int, view: View) {
                val newFragment = PhraseDialogFragment()
                val args = Bundle()
                args.putInt("POSITION", position)
                args.putString("CONTENT", modSamplePhrases[position].sample)
                newFragment.arguments = args
                val fm = fragmentManager
                newFragment.show(fm, "STF")
            }
        })
    }

    fun getDataFromDialog(pos: Int, dialogText: String) {
        modSamplePhrases[pos].sample = dialogText
        println("item " + pos + ": " + modSamplePhrases[pos].sample)
        phraseListAdapter.notifyDataSetChanged()
    }

I have tried re-creating the adapter after modifying the data

phraseListAdapter = PhraseListAdapter(modSamplePhrases)

I've also tried getting a reference to the RecyclerView and resetting the adapter on it

recyclerView?.adapter = phraseListAdapter

But still nothing.

PhraseListAdapter code:

class PhraseViewHolder(inflater: LayoutInflater, parent: ViewGroup) :
    RecyclerView.ViewHolder(inflater.inflate(R.layout.list_item, parent, false)) {
    private var indexView: TextView? = null
    private var sampleView: TextView? = null

    init {
        indexView = itemView.findViewById(R.id.text_index)
        sampleView = itemView.findViewById(R.id.text_sample)
    }

    fun bind(phrase: Phrase) {
        indexView?.text = phrase.sample
        sampleView?.text = phrase.index.toString()
    }
}



class PhraseListAdapter (private val list: MutableList<Phrase>) : RecyclerView.Adapter<PhraseViewHolder>(){

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PhraseViewHolder {
        val inflater = LayoutInflater.from(parent.context)
        return PhraseViewHolder(inflater, parent)
    }

    override fun onBindViewHolder(holder: PhraseViewHolder, position: Int) {
        val phrase: Phrase = list[position]
        holder.bind(phrase)
    }

    override fun getItemCount(): Int = list.size

}

´´´

Solution

  • Facepalm. Problem was I was calling the getDataFromDialog() function from outside the fragment like so:

    PhraseRecyclerFragment().getDataFromDialog(pos, "" + textViewContent.text)
    

    So I needed to put the function in a companion object:

        companion object {
            var modSamplePhrases = PhraseData().samplePhrases
            var phraseListAdapter = PhraseListAdapter(modSamplePhrases)
            fun getDataFromDialog(pos: Int, dialogText: String) {
                modSamplePhrases[pos].sample = dialogText
                phraseListAdapter.notifyDataSetChanged()
            }
    

    to be able to call it with:

    PhraseRecyclerFragment.getDataFromDialog(pos, "" + textViewContent.text)
    

    And now everything works as it should. My bad. Thanks to everyone who tried to help.