Home > Back-end >  Do I have to free/destroy ArrayAdapters in Android?
Do I have to free/destroy ArrayAdapters in Android?

Time:10-16

Do I have to free my custom ArrayAdapters in fragments, like I do it with binding? And also what about ArrayList that holds the data?

Inside my Fragment class I have:

private var binding: FragmentUhfReadBinding? = null            // init onCreateView, free onDestroyView, use onViewCreated
private var listAdapter: ReadUhfTagInfoItemViewAdapter? = null // init in onViewCreated
private val arrayList: ArrayList<ReadUhfTagInfo?>? = ArrayList()

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

override fun onDestroyView() {
    super.onDestroyView()
    binding = null
    // do I have to set `listAdapter` to null here?
}

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

    super.onViewCreated(view, savedInstanceState)
    listAdapter = ReadUhfTagInfoItemViewAdapter(this.context, arrayList)

    binding!!.lvData.adapter = listAdapter
}

CodePudding user response:

Yes, because your adapter is referencing a context (which is the attached Activity).

It's also referencing a list that you have created only in your Fragment, but it's debatable whether you should care if that's leaked. It would be more typical for backing list data to be in a ViewModel so it could be reused, in which case this list reference your adapter is holding wouldn't be a problem.

Although your example doesn't show it, it's also very common for an adapter to expose some kind of listener for view interactions. So when you add this, and your listeners capture references to other stuff in the fragment, then the adapter would also be leaking the memory of those things.


However, it is not common in the first place to need your binding and your adapter to be in class properties. If you use them solely within onViewCreated() and functions called by onViewCreated(), then you don't need to worry about clearing references to them, and you won't have the ugly use of !!, so it will be more robust.

Instead of inflating a view with onCreateView(), you can pass a layout id to the superconstructor, and then create your binding by calling bind with the pre-existing view in onCreateView().

class MyFragment: Fragment(R.layout.fragment_uhf_read) {

    private val arrayList: ArrayList<ReadUhfTagInfo?> = ArrayList()

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

        val binding = FragmentUhfReadBinding.bind(view)
        val listAdapter = ReadUhfTagInfoItemViewAdapter(this.context, arrayList)

        binding.lvData.adapter = listAdapter

        // ... other code using binding and listAdapter
    }
}
  • Related