如何在没有内存异常的情况下使用RealmBaseAdapter?

时间:2015-04-01 16:36:29

标签: android out-of-memory realm realm-base-adapter

我想弄清楚使用RealmBaseAdapter的正确方法是什么。

背景

  • 我有一个带有单个活动和许多片段的应用。
  • 主屏幕是一个片段,其中包含带有子片段的ViewPager(操作栏中有选项卡)。
  • 每个子片段都包含一个列表视图,该视图使用RealmBaseAdapter的子类显示领域结果。
  • 当用户点击其中一个列表视图中的项目时,会显示一个内部片段(它将主片段替换为其所有子片段)。
  • 要使RealmBaseAdapter工作,必须打开创建RealmResults的Realm对象(在getInstance之后和关闭之前),所以我有一个基本片段,它在onStart中创建一个Realm实例并在onDestroy中关闭它。

现在问题
在应用程序中有太多与内存相关的崩溃,我认为我理解其中的原因 问题是总是至少有一个开放的Realm,它避免了它被清理 意味着领域一直在记忆中成长,永远不会有机会被清理。

根据领域的github repo中的几个与内存相关的问题,我理解应该尽可能短的操作打开和关闭领域,但它与RealmBaseAdapter要求原始领域对象打开的事实形成对比一生都有。

任何帮助/想法都将不胜感激。

2 个答案:

答案 0 :(得分:0)

https://realm.io/docs/java/0.80.0/#faq的常见问题解答中解释了为什么领域的文件大小可能会增加(请参阅"大领域文件大小")。

我建议您在应用程序启动或恢复时(以及在打开Realm实例之前)压缩您的Realm文件。方法Realm.compactRealmFile()是您应该寻找的方法(请参阅https://realm.io/docs/java/0.80.0/api/io/realm/Realm.html#compactRealmFile-android.content.Context-)。

答案 1 :(得分:0)

来自境界的克里斯蒂安。如果没有关于代码的更多细节,可能很难猜出确切的原因,但下面是关于Realm如何工作的一些提示可能对您有所帮助。

  • 您可以根据需要在UI线程上打开尽可能多的Realm实例。 Realm使用ThreadLocal缓存来缓存Realms。因此,在onCreate中打开Realms并在onDestroy中关闭它们是完全可行的模式。

  • 所有RealmBaseAdapter都使用相同的Realm缓存版本。

  • 如果您在多个线程上打开相同的Realm,Realm将使用额外的内存,因为它必须处理这些Realms可能是不同的版本。忘记关闭后台线程中的域是OOM错误的最常见原因。特别是如果你生成自己的线程而不是使用Threadpools。

  • 使用多个Realm文件会增加内存使用量,因为它们是完全独立的数据库。

  • 在紧密循环中迭代大型RealmResults(例如,在动画重绘期间)会导致OOM错误。这是因为Realm目前使用终结器来清理本机内存,而终结器的速度非常慢,以至于GC线程可能无法跟上。我们在此解决了这个问题:https://github.com/realm/realm-java/pull/922,但它还没有合并,因为它对整体性能也有负面影响。请注意,呈现ListAdapter不是一个大型数据集,因为它只呈现可见项,但如果您在较长时间内快速滚动数千个对象,则可能会遇到OOM。

我希望上述内容有所帮助,但如果您仍然看到这些问题,我建议您在https://github.com/realm/realm-java创建一个GitHub问题,以便我们能够深入了解这一问题。