Deb*_*jee 6 android memory-leaks android-fragments android-studio leakcanary
我知道将片段事务添加到backstack,然后从该片段移动到另一个片段,reference of the previous fragment's view is still available并且只有在按下后退按钮时它才会被销毁。为了避免这种情况,I have set the view to null in onDestroyView但问题是,leakcanary still shows view is not null and the view reference is still available而记录视图却说它为空。
为什么会这样?另外,如果我错了或遗漏了什么,请纠正我。
片段类-
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
}
Run Code Online (Sandbox Code Playgroud)
LeakCanary 分析日志——
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
====================================
Run Code Online (Sandbox Code Playgroud)
您仍然保留对btnSignUpafter的引用onDestroyView-这就是泄漏的原因。您必须删除对刚刚销毁的视图中所有视图的所有引用。
因此,您应该使用相同的方法(使其成为 nullable var)或根本不保留btnSignUp对 Fragment的引用- 至少在您的代码示例中,它很容易成为局部变量。(实际上,这同样适用于您的mView- 您将View用作 的输入onViewCreated(),没有理由在 Fragment 级别保留它)。
| 归档时间: |
|
| 查看次数: |
2964 次 |
| 最近记录: |