0

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

}

´´´
eggdeng
  • 148
  • 9
  • Can you add code of PhraseListAdapter here? – Arslan Shoukat Feb 05 '20 at 16:19
  • Thanks for the fast response. I've added the adapter code. – eggdeng Feb 05 '20 at 17:19
  • You recreate the adapter, but the recyclerview points to the old istance, so obviously notifying the new instance won't do anything – gpunto Feb 05 '20 at 17:33
  • Just like @gpunto pointed out, You are recreating adapter instance but not setting it to the recyclerview. You can set it the new one and omit notifydatasetchanged() call. What you could try is to have a update method inside the adapter, call the update method and inside it call notifiydatasetchanged() after adding the data to your data list. I think that should work. – Jude Osbert K Feb 05 '20 at 17:36
  • I get the point about recreating the adapter. I think I muddied the water by leaving that line in the post so I've removed it. I also tried resetting the adapter on the RecyclerView as well as both options in tandem but, really, neither should be necessary. I also tried putting the update method inside the adapter but with the same result - none. Despite extensive searching, I have yet to find a working example of notifyDatasetChanged() in Kotlin anywhere. – eggdeng Feb 05 '20 at 17:50

1 Answers1

0

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.

eggdeng
  • 148
  • 9