LeakCanary:View.mContext引用了已销毁的activity(自定义View)

3

我正在尝试解决内存泄漏的问题。我有一个CustomActivity,它添加了一个包含com.example.CustomViewGroupFragment,后者引用了一个com.example.CustomView

class CustomFragment : Fragment() {
    override fun onViewCreated(view:View, savedInstanceState:Bundle?) 
    {
        view.findViewById<CustomViewGroup>(R.id.custom_view_group).also { vg ->

            lifecycleScope.launch {
                ...

                lifecycleScope.launch {
                    vg.doSomethingInASuspendMethod()
                }
            }
        }
    }
}

class CustomViewGroup : ConstraintLayout {

    internal var customView: CustomView? = null

    init {
        View.inflate(context, R.layout.custom_view_group, this)
        customView = findViewById(R.id.custom_view)
        ...
    }

    //I've tried numerous things below, but none of them seem to help
    override fun onDestroy(owner: LifecycleOwner) {
        super.onDestroy(owner)
        customView?.onDestroy(owner)
        super.onDetachedFromWindow()
        customView = null
        removeAllViews() 
    }
}

我已经尝试了onDestroy中的各种方法,但似乎都没有帮助。我认为这与嵌套协程作用域有关。

58913 bytes retained by leaking objects
    Displaying only 1 leak trace out of 2 with the same signature
    ┬───
    │ GC Root: Java local variable
    │
    ├─ kotlinx.coroutines.scheduling.CoroutineScheduler$Worker thread
    │    Leaking: UNKNOWN
    │    Thread name: 'DefaultDispatcher-worker-1'
    │    ↓ CoroutineScheduler$Worker.<Java Local>
    │                                ~~~~~~~~~~~~
    ├─ com.example.CustomView instance
    │    Leaking: YES (View.mContext references a destroyed activity)
    │    mContext instance of com.example.CustomActivity with mDestroyed = true
    │    View#mParent is set
    │    View#mAttachInfo is null (view detached)
    │    View.mID = R.id.null
    │    View.mWindowAttachCount = 1
    │    ↓ CustomView.mContext
    ╰→ com.example.CustomActivity instance
    ​     Leaking: YES (ObjectWatcher was watching this because com.example.CustomActivity received Activity#onDestroy() callback and Activity#mDestroyed is true)
1个回答

2

事实证明,我正在一个while循环中执行某些操作,而我需要检查协程是否仍然处于活动状态。

 
    internal suspend fun doSomethingInASuspendMethod() {
        withContext(Dispatchers.Default) {
            while (isActive) { // was while(true) before the fix
                ...
            }
        }
    }

取消协作:

与Android的AsyncTask类似,协程也是取消协作的。在调用协程作业的cancel方法时,isActive标志将被设置为false,但作业将继续运行。这意味着,如果您在协程中有一个长时间运行的循环,但没有检查isActive标志以退出,则该循环将继续直到完成。在此示例中,检查isActive标志的好地方可能是在每次循环迭代之后。

https://proandroiddev.com/cancelling-kotlin-coroutines-1030f03bf168#:~:text=Cancellation%20Cooperative&text=This%20means%20that%20if%20you,loop%20will%20continue%20until%20complete.


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接