android - 数据绑定内存泄漏
问题描述
当我打开使用数据绑定的片段时,发生内存泄漏,如下所示。有没有合适的答案来解决这个问题?
我用了
- 数据绑定
- 导航
- 生命周期
- 材质ui
┬───
│ GC Root: System class
│
├─ androidx.databinding.ViewDataBinding class
│ Leaking: NO (a class is never leaking)
│ ↓ static ViewDataBinding.sReferenceQueue
│ ~~~~~~~~~~~~~~~
├─ java.lang.ref.ReferenceQueue instance
│ Leaking: UNKNOWN
│ ↓ ReferenceQueue.head
│ ~~~~
├─ androidx.databinding.ViewDataBinding$WeakListener instance
│ Leaking: UNKNOWN
│ ↓ ViewDataBinding$WeakListener.mObservable
│ ~~~~~~~~~~~
├─ androidx.databinding.ViewDataBinding$LiveDataListener instance
│ Leaking: UNKNOWN
│ ↓ ViewDataBinding$LiveDataListener.mLifecycleOwner
│ ~~~~~~~~~~~~~~~
╰→ com.norm.news.ui.source.NewsSourceFragment instance
Leaking: YES (ObjectWatcher was watching this because com.norm.news.ui.source.NewsSourceFragment received Fragment#onDestroy() callback and Fragment#mFragmentManager is null)
key = 55b68d7d-56bb-46ff-ad17-e29f01b6a808
watchDurationMillis = 5207
retainedDurationMillis = 139
key = 2fc4bd04-641e-4bea-8e13-71650f6e2a25
METADATA
Build.VERSION.SDK_INT: 24
Build.MANUFACTURER: samsung
LeakCanary version: 2.1
App process name: com.norm.news.debug
Analysis duration: 12283 ms
这是我的片段中的片段代码。
此代码引用自Android Kotlin Fundamentals 05.3: Data binding with ViewModel and LiveData
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val binding: FragmentNewsSourceBinding = DataBindingUtil.inflate(
inflater,
R.layout.fragment_news_source,
container,
false
)
// Specify the current activity as the lifecycle owner of the binding.
// This is necessary so that the binding can observe LiveData updates.
binding.lifecycleOwner = this
val application = requireNotNull(this.activity).application
val viewModelFactory = NewsSourceViewModelFactory(application)
val newsSourceViewModel =
ViewModelProviders.of(this, viewModelFactory).get(NewsSourceViewModel::class.java)
binding.newsSourceViewModel = newsSourceViewModel
binding.rvSourceLists.adapter = NewsSourceAdapter(NewsSourceAdapter.OnClickListener {
newsSourceViewModel.displayNewsSourceDetails(it)
})
newsSourceViewModel.navigateToSelectedItem.observe(viewLifecycleOwner, Observer {
if (it != null) {
this.findNavController()
.navigate(NewsSourceFragmentDirections.actionNewsSourceFragmentToNewsFragment(it.id))
newsSourceViewModel.displayNewsSourceDetailsComplete()
}
})
return binding.root
}
解决方案
基于读取泄漏跟踪和源代码,这看起来像是数据绑定库中的一个错误。我不确定是什么触发了它。
有一个引用队列,当弱引用的实例弱可达时,WeakListener 实例被添加到其中。所以我们知道在这种情况下,这就是监听器所处的状态。WeakRefs enqueued 将一直留在那里,直到通过消费代码(这里是数据绑定库)处理队列,这通常不是问题,因为 ref 为空。然而,这里的weakref有一个mObservable字段,它最终会泄漏一个生命周期所有者,它是一个被破坏的片段。这将在下一次处理 ref 队列时停止泄漏,尽管尚不清楚何时发生。
所以这看起来像是数据绑定库如何处理弱引用的设计缺陷/错误。
您可能应该使用此上下文向该项目提交错误,并提供额外的详细信息,例如 lib 版本号。提供堆转储(易于从泄漏卡纳利共享)也会有所帮助。
推荐阅读
- java - Selenium Java:无法通过自定义上传上传文件
- networking - 是否可以从目标 IP 获取网站 url?
- javascript - 如何在 ES6 中实现命名构造函数
- arduino - FreeRTOS 内核如何暂停 Arduino UNO 上的任务?
- git - 移动整个 git 目录
- string - 使用 T-SQL 提取字符串
- kubernetes - Kubernetes 外部供应商与 CSI
- spring-boot - 在压力/负载测试期间,活性探针因执行器端点而失败?
- javascript - 如何在 1 个表中显示 2 个类 JavaScript id
- bash - 如何将 kubectl 命令的输出解析为 bash 脚本的数组