领域造成大量ANR

时间:2015-07-20 16:16:18

标签: android realm

在我自己的测试中,我没有遇到这个问题但是一旦我的应用程序发布,ANR开始涌入。我的应用程序目前有22个ANR,其中一些被报告为100次。所有跟踪似乎都来自于尝试在UI线程上创建新的Realm实例。

"main" prio=5 tid=1 MONITOR
| group="main" sCount=1 dsCount=0 obj=0x4183ede0 self=0x417548b8
| sysTid=19680 nice=0 sched=0/0 cgrp=apps handle=1073975684
| state=S schedstat=( 2816413167 710323137 3658 ) utm=215 stm=66 core=1
at io.realm.Realm.createAndValidate(Realm.java:~495)
- waiting to lock <0x41df9c98> held by tid=12          (IntentService[UASyncService])
at io.realm.Realm.create(Realm.java:486)
at io.realm.Realm.getInstance(Realm.java:404)
at io.realm.Realm.getInstance(Realm.java:366)
at io.realm.Realm.getInstance(Realm.java:347)

我认为,正如beeender所提到的,这个问题的根源是我在工作线程中有一个开放的Realm事务,它阻止了我在UI线程上获取Realm实例导致ANR的尝试。

我有解决方案后会再次更新。

*编辑:添加了更新信息。

2 个答案:

答案 0 :(得分:3)

领域不再有这个问题。

作为参考我当时的解决方案是:

感谢beeender指出我正确的方向并链接此PR https://github.com/realm/realm-java/pull/1297

<强>问题

当存在挂起的Realm事务时,对其他线程的Realm.getInstance的任何调用都将阻塞,直到挂起的事务已提交或取消。

在我的情况下,我有一个IntentService,用现有的用户数据填充我的Realm,同时我尝试通过在UI线程上查询Realm来显示任何当前数据。尽管查询很简单并且通常不会导致任何问题,但如果IntentService中存在挂起的事务,则将阻止调用Realm.getInstance,阻止UI线程,从而可能导致ANR。

我首次尝试解决方案是拉出beeender的PR分支并创建一个jar。我相信这个修复程序确实让我更进一步,允许创建Realm实例而不会阻塞,但UI线程仍被我尝试在UI线程上执行的小事务阻止。

<强>解决方案

我实施的解决方案涉及几个步骤:

  • 为我的所有模型创建重复的对象。重复项不会扩展RealmObject(因为RealmObjects不能跨线程使用。)
  • 将对Realm的所有访问移至后台线程。基本上我将查询包装在AsyncTasks中,并添加了返回模型的非RealmObject版本的侦听器。
  • 制作更多小型交易而不是更少的大型交易。以前我在创建许多新RealmObject的循环的任何一侧开始并提交事务,我现在开始并为每个对象提交事务。这样做的目的是减少Realm处于打开事务状态的总不间断时间,这样我为UI提供数据的查询就可以完成而无需等待很长时间。

<强>结论

我最初对使用Realm犹豫不决,因为它仍然处于测试阶段以及不能跨线程使用RealmObjects的警告。经过一些测试后,我确信我可以毫无问题地在UI线程上执行简单查询(尽管我的内心仍然有一种内疚感。)

整体领域是一个值得关注的伟大项目,但我觉得它还没有为大型商业项目做好准备。在这个项目中使用Realm可能已经节省了一些时间,但它使许多不满的客户和难以诊断的问题付出了代价。

*编辑:澄清问题。

答案 1 :(得分:0)

Realm's introduction example显示他们使用AsyncTask进行读写操作。

任何代价高昂的I / O,无论是来自网络,数据库还是大型文件,都应该远离主线程,因为它会导致UI缓慢。在没有看到你的代码的情况下,我猜想如果你得到一个ANR,你可能会为主线程做一些过于复杂的事情。