Search code examples
androidkotlinandroid-databinding

Android DataBinding is leaking Memory


I'm using data-binding and I have declared a lateinit var for the binding and when I'm going to different fragment Leaky canary showing a leak.

Fragment

class HomeFragment : BottomNavViewHostBaseFragment() {

    private lateinit var viewModel: HomeViewModel
    private lateinit var binding: FragmentHomeBinding

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        viewModel = ViewModelProviders.of(this).get(HomeViewModel::class.java)
        binding = DataBindingUtil.inflate(inflater, R.layout.fragment_home, container, false)
        binding.lifecycleOwner = viewLifecycleOwner
        binding.viewModel = viewModel
        return binding.root
    }

   ...
}

Here is the Info from Leaky Carny

androidx.constraintlayout.widget.ConstraintLayout has leaked:
Toast$TN.mNextView
↳ LinearLayout.mContext
↳ MainActivity.navigationView
↳ NavigationView.listener
↳ BaseFragment$setNavigationDrawerItemSelectedListener$1.this$0 (anonymous implementation of com.google.android.material.navigation.NavigationView$OnNavigationItemSelectedListener) ↳ OrdersHostFragment.mFragmentManager
↳ FragmentManagerImpl.mActive
↳ HashMap.table
↳ array HashMap$HashMapEntry[].[0]
↳ HashMap$HashMapEntry.value
↳ HomeFragment.!(binding)!
↳ FragmentHomeBindingImpl.!(mboundView0)!
↳ ConstraintLayout

How do I solve this and Should I need to do binding=null inside onDestroyView? But if I need to do this then what is the point of binding.lifecycleOwner = viewLifecycleOwner then?


Solution

  • According to fragment lifecycle, onDestroyView() was called, but fragment is not fully destroyed - so onDestroy() is not called. In that case, if you don't reset binding property by hand, it references view tree (it's some kind of leak).

    But if I need to do this then what is the point of binding.lifecycleOwner = viewLifecycleOwner then?

    If you supply LifecycleOwner to binding object, it allows to observe all LiveData objects inside generated binding class. But it can't know about external references on binding instance outside (from any other classes of your project) - that's why it can't automatically reset them.