I used Jetpack's navigation to manage Fragment, which uses databinding in Fragment.
Did not add other code. The memory leak is HomeFragment.databinding.root, which is a LinearLayout, and LinearLayout does not put anything. The LeakCanary message is shown below:
I used Jetpack's navigation to manage Fragment, which uses databinding in Fragment.
Did not add other code. The memory leak is HomeFragment.databinding.root, which is a LinearLayout, and LinearLayout does not put anything. The LeakCanary message is shown below:
ApplicationLeak(className=android.widget.LinearLayout, leakTrace=
┬
├─ android.app.ActivityThread
│ Leaking: NO (ActivityThread↓ is not leaking and a class is never leaking)
│ GC Root: System class
│ ↓ static ActivityThread.sCurrentActivityThread
├─ android.app.ActivityThread
│ Leaking: NO (ArrayMap↓ is not leaking)
│ ↓ ActivityThread.mActivities
├─ android.util.ArrayMap
│ Leaking: NO (Object[]↓ is not leaking)
│ ↓ ArrayMap.mArray
├─ java.lang.Object[]
│ Leaking: NO (ActivityThread$ActivityClientRecord↓ is not leaking)
│ ↓ array Object[].[1]
├─ android.app.ActivityThread$ActivityClientRecord
│ Leaking: NO (MainActivity↓ is not leaking)
│ ↓ ActivityThread$ActivityClientRecord.activity
├─ com.ukex.module.index.ui.MainActivity
│ Leaking: NO (FragmentController↓ is not leaking and Activity#mDestroyed is false)
│ ↓ MainActivity.mFragments
├─ androidx.fragment.app.FragmentController
│ Leaking: NO (FragmentActivity$HostCallbacks↓ is not leaking)
│ ↓ FragmentController.mHost
├─ androidx.fragment.app.FragmentActivity$HostCallbacks
│ Leaking: NO (FragmentManagerImpl↓ is not leaking)
│ ↓ FragmentActivity$HostCallbacks.mFragmentManager
├─ androidx.fragment.app.FragmentManagerImpl
│ Leaking: NO (NavHostFragment↓ is not leaking)
│ ↓ FragmentManagerImpl.mPrimaryNav
├─ androidx.navigation.fragment.NavHostFragment
│ Leaking: NO (FragmentManagerImpl↓ is not leaking and Fragment#mFragmentManager is not null)
│ ↓ NavHostFragment.mChildFragmentManager
├─ androidx.fragment.app.FragmentManagerImpl
│ Leaking: NO (HashMap↓ is not leaking)
│ ↓ FragmentManagerImpl.mActive
├─ java.util.HashMap
│ Leaking: NO (HashMap$Node[]↓ is not leaking)
│ ↓ HashMap.table
├─ java.util.HashMap$Node[]
│ Leaking: NO (HashMap$Node↓ is not leaking)
│ ↓ array HashMap$Node[].[0]
├─ java.util.HashMap$Node
│ Leaking: NO (HomeFragment↓ is not leaking)
│ ↓ HashMap$Node.value
├─ com.ukex.module.index.ui.HomeFragment
│ Leaking: NO (Fragment#mFragmentManager is not null)
│ ↓ HomeFragment.dataBinding
│ ~~~~~~~~~~~
├─ com.ukex.databinding.HomeFragmentBindingImpl
│ Leaking: UNKNOWN
│ ↓ HomeFragmentBindingImpl.mRoot
│ ~~~~~
╰→ android.widget.LinearLayout
Leaking: YES (ObjectWatcher was watching this)
mContext instance of com.ukex.module.index.ui.MainActivity with mDestroyed = false
View#mParent is null
View#mAttachInfo is null (view detached)
View.mWindowAttachCount = 1
key = 965e1901-f293-454b-b8c2-80b869d64f9a
watchDurationMillis = 21809
retainedDurationMillis = 16807
, retainedHeapByteSize=6255)
class HomeFragment : BaseVMFragment<HomeViewModel>() {
private lateinit var dataBinding: HomeFragmentBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
dataBinding =
DataBindingUtil.inflate(inflater, R.layout.home_fragment, container, false)
return dataBinding.root
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
dataBinding.apply {
vm = mViewModel
lifecycleOwner = this@HomeFragment
}
btnLogin.setOnClickListener {
startActivity(Intent(context, LoginAct::class.java))
}
}
override fun bindObserve() {
super.bindObserve()
mViewModel?.user?.observe(this, Observer {
if (it != null)
ToastUtils.showLong(it.username)
})
}
override fun providerVMClass(): Class<HomeViewModel>? {
return HomeViewModel::class.java
}
}