即使在设置为 null 后片段绑定仍在泄漏

Fragment binding is leaking even after setting null

根据 android docs 我已经实现了简单的片段,但是当我移动到下一个片段时,它开始在 _binding 中泄漏,即使我已经设置了绑定 null。

这是我的泄漏堆栈跟踪

37740 bytes retained by leaking objects
Signature: 7162f0f053a181182714235f17d7e8c36154eb81
┬───
│ GC Root: Global variable in native code
│
├─ android.database.ContentObserver$Transport instance
│    Leaking: NO (LoginFragment↓ is not leaking)
│    ↓ ContentObserver$Transport.mContentObserver
├─ android.widget.Editor$HandleViewShowObserver instance
│    Leaking: NO (LoginFragment↓ is not leaking)
│    ↓ Editor$HandleViewShowObserver.mContext
├─ dagger.hilt.android.internal.managers.ViewComponentManager$FragmentContextWrapper instance
│    Leaking: NO (LoginFragment↓ is not leaking)
│    ViewComponentManager$FragmentContextWrapper wraps an Activity with Activity.mDestroyed false
│    ↓ ViewComponentManager$FragmentContextWrapper.fragment
├─ com.ics.homework.ui.auth.LoginFragment instance
│    Leaking: NO (WelcomeFragment↓ is not leaking and Fragment#mFragmentManager is not null)
│    ↓ LoginFragment.mFragmentManager
├─ androidx.fragment.app.FragmentManagerImpl instance
│    Leaking: NO (WelcomeFragment↓ is not leaking)
│    ↓ FragmentManagerImpl.mFragmentStore
├─ androidx.fragment.app.FragmentStore instance
│    Leaking: NO (WelcomeFragment↓ is not leaking)
│    ↓ FragmentStore.mActive
├─ java.util.HashMap instance
│    Leaking: NO (WelcomeFragment↓ is not leaking)
│    ↓ HashMap.table
├─ java.util.HashMap$Node[] array
│    Leaking: NO (WelcomeFragment↓ is not leaking)
│    ↓ HashMap$Node[].[1]
├─ java.util.HashMap$Node instance
│    Leaking: NO (WelcomeFragment↓ is not leaking)
│    ↓ HashMap$Node.value
├─ androidx.fragment.app.FragmentStateManager instance
│    Leaking: NO (WelcomeFragment↓ is not leaking)
│    ↓ FragmentStateManager.mFragment
├─ com.ics.homework.ui.auth.WelcomeFragment instance
│    Leaking: NO (Fragment#mFragmentManager is not null)
│    ↓ WelcomeFragment._binding
│                      ~~~~~~~~
├─ com.ics.homework.databinding.FragmentWelcomeBindingImpl instance
│    Leaking: UNKNOWN
│    ↓ FragmentWelcomeBindingImpl.mRoot
│                                 ~~~~~
╰→ androidx.constraintlayout.widget.ConstraintLayout instance
​     Leaking: YES (ObjectWatcher was watching this because com.ics.homework.ui.auth.WelcomeFragment received Fragment#onDestroyView() callback (references to its views should be cleared to prevent leaks))
​     key = a1bab73c-de04-4e36-bda1-b29a54da8348
​     watchDurationMillis = 22798
​     retainedDurationMillis = 17792
​     mContext instance of com.ics.homework.ui.auth.AuthActivity with mDestroyed = false
​     View#mParent is null
​     View#mAttachInfo is null (view detached)
​     View.mWindowAttachCount = 1
====================================
0 LIBRARY LEAKS

这是我的实现

class WelcomeFragment : Fragment() {
private var _binding: FragmentWelcomeBinding? = null
private val binding get() = _binding!!

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

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    binding.handler = onClickListener
}

private val onClickListener = View.OnClickListener { view ->
    with(binding) {
        when (view.id) {
            btnLoginSignup.id -> {
                val action = WelcomeFragmentDirections.actionWelcomeFragmentToLoginFragment()
                findNavController().navigate(action)
            }
            tvHelpline.id,
            tvHelplineNumber.id -> {
                val intent = Intent(Intent.ACTION_DIAL)
                intent.data = Uri.parse("tel:0123456789")
                startActivity(intent)
            }
        }
    }
}

override fun onDestroy() {
    super.onDestroy()
    binding.handler = null
    _binding = null
}

}

在来自文档的示例中,绑定在 OnDestroyView() 方法中设置为 null,而不是在 OnDestroy() 中。据我所知,当您将 Fragment A 替换为 Fragment B 并将 Fragment A 添加到 backstack 时,不会调用 Fragment A 的 OnDestroy() 方法。这就是为什么您的绑定不为空。