You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetpack Compose中Clickable未触发仍出现内存泄漏原因咨询

两种Compose写法触发内存泄漏的原因解析

第一种写法的问题

你以为用WeakReference能规避强引用,但实际上完全没起作用:

  • clickable修饰符会持有点击事件的Lambda,而这个Lambda在创建WeakReference时已经强引用了this@MyActivity——WeakReference只是内部存了弱引用,但Lambda本身已经把Activity实例抓牢了。
  • 只要这个Text所在的Compose UI树没被正确销毁(比如配置变化后旧Activity的Compose状态还留着),Lambda就会一直攥着Activity的强引用,GC根本回收不了它,直接触发泄漏。
  • 哪怕你不点这个组件,从组件创建的那一刻起,Lambda就已经被修饰符持有了,泄漏也就发生了。

这里的逻辑错误:你把WeakReference的创建放在Lambda内部,这改变不了Lambda捕获Activity强引用的事实。就算要这么做,也得先在外部创建WeakReference,再让Lambda去引用这个WeakReference对象(但Compose里本来就不建议直接拿Activity引用)。

第二种写法的问题

核心是强引用捕获+协程作用域的残留持有:

  • val activity = activity_ as? MyActivity拿到了Activity的强引用,随后被clickable的Lambda捕获,而这个Lambda会被Modifier持有,进而绑定到Compose的UI树上。
  • rememberCoroutineScope()返回的作用域是和当前Compose可组合项的生命周期绑定的,但如果Activity销毁后,这个作用域因为未取消的协程、UI树残留等原因没被清理,协程作用域会间接持有Lambda,Lambda又攥着Activity的强引用,自然就泄漏了。
  • 同样,不管点不点组件,只要组件被创建,Lambda就已经捕获了Activity的强引用,泄漏从一开始就存在——协程的launch只是执行入口,不是泄漏的起因。

另外提一句:Compose里直接持有Activity实例是非常不推荐的,应该用LocalContext.current拿上下文,尽量通过ViewModel这类生命周期安全的组件处理业务逻辑,别直接抓Activity/Fragment的引用。

内容的提问来源于stack exchange,提问作者LXJ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 06:33:20