I know that adding a fragment transaction to the backstack and then moving from that fragment to another fragment, the reference of the previous fragment's view is still available and it only gets destroyed when the back button is pressed.
And to avoid this, I have set the view to null in onDestroyView but the problem is, leakcanary still shows view is not null and the view reference is still available whereas logging the view says it is null.
Why is it so ? Also, please correct me if I'm wrong or missing anything.
The fragment class-
private var mView: View? = null
private lateinit var btnSignUp: Button
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
mView = inflater.inflate(R.layout.fragment_login, container, false)
return mView
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
btnSignUp = view.findViewById(R.id.btnSignUp)
btnSignUp.setOnClickListener {
// calling function changeFragment()
changeFragment(SignUpFragment(), FragmentsTag.SIGNUP_FRAGMENT)
}
}
override fun onDestroyView() {
super.onDestroyView()
mView=null
}
LeakCanary Analysis logs --
HEAP ANALYSIS RESULT
====================================
1 APPLICATION LEAKS
References underlined with "~~~" are likely causes.
Learn more at https://squ.re/leaks.
43817 bytes retained by leaking objects
Signature: 6e77557c8a679dd41391c1c5badaac98217366ad
┬───
│ GC Root: System class
│
├─ leakcanary.internal.InternalLeakCanary class
│ Leaking: NO (MainActivity↓ is not leaking and a class is never leaking)
│ ↓ static InternalLeakCanary.resumedActivity
├─ com.example.foodrunner.activities.MainActivity instance
│ Leaking: NO (LoginFragment↓ is not leaking and Activity#mDestroyed is false)
│ ↓ MainActivity.mFragments
├─ androidx.fragment.app.FragmentController instance
│ Leaking: NO (LoginFragment↓ is not leaking)
│ ↓ FragmentController.mHost
├─ androidx.fragment.app.FragmentActivity$HostCallbacks instance
│ Leaking: NO (LoginFragment↓ is not leaking)
│ ↓ FragmentActivity$HostCallbacks.mFragmentManager
├─ androidx.fragment.app.FragmentManagerImpl instance
│ Leaking: NO (LoginFragment↓ is not leaking)
│ ↓ FragmentManagerImpl.mActive
├─ java.util.HashMap instance
│ Leaking: NO (LoginFragment↓ is not leaking)
│ ↓ HashMap.table
├─ java.util.HashMap$HashMapEntry[] array
│ Leaking: NO (LoginFragment↓ is not leaking)
│ ↓ HashMap$HashMapEntry[].[0]
├─ java.util.HashMap$HashMapEntry instance
│ Leaking: NO (LoginFragment↓ is not leaking)
│ ↓ HashMap$HashMapEntry.value
├─ com.example.foodrunner.fragments.LoginFragment instance
│ Leaking: NO (Fragment#mFragmentManager is not null)
│ Fragment.mTag=Login Fragment
│ ↓ LoginFragment.btnLogin
│ ~~~~~~~~
├─ com.google.android.material.button.MaterialButton instance
│ Leaking: YES (View detached and has parent)
│ mContext instance of com.example.foodrunner.activities.MainActivity with mDestroyed = false
│ View#mParent is set
│ View#mAttachInfo is null (view detached)
│ View.mID = R.id.btnLogin
│ View.mWindowAttachCount = 1
│ ↓ MaterialButton.mParent
╰→ androidx.constraintlayout.widget.ConstraintLayout instance
Leaking: YES (ObjectWatcher was watching this because com.example.foodrunner.fragments.LoginFragment received Fragment#onDestroyView() callback (references to its views should be cleared to prevent leaks))
key = b72a82a6-b9dd-46c6-afb2-0ea6c7025001
watchDurationMillis = 9582
retainedDurationMillis = 4582
key = 0554b63a-c700-4c86-a451-b0daae06607a
watchDurationMillis = 9581
retainedDurationMillis = 4580
mContext instance of com.example.foodrunner.activities.MainActivity with mDestroyed = false
View#mParent is null
View#mAttachInfo is null (view detached)
View.mWindowAttachCount = 1
====================================