领域造成大量ANR

Mic*_*Dev 6 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)
Run Code Online (Sandbox Code Playgroud)

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

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

*编辑:添加了更新的信息.

Mic*_*Dev 3

Realm 不再有这个问题。

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

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

问题

当存在待处理的领域事务时,对Realm.getInstance不同线程的任何调用都将阻塞,直到提交或取消待处理的事务。

就我而言,我有一个 IntentService,它用现有的用户数据填充我的 Realm,同时我尝试通过在 UI 线程上查询 Realm 来显示任何当前数据。虽然查询很简单并且通常不会引起任何问题,但如果 IntentService 中有待处理的事务,调用Realm.getInstance将被阻塞,从而阻塞 UI 线程,可能导致 ANR。

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

解决方案

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

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

结论

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

总的来说,Realm 是一个值得关注的伟大项目,但我觉得它还没有为大型商业项目做好准备。在这个项目上使用 Realm 可能会节省一些前期时间,但它会让许多不满意的客户付出代价,而且问题也很难诊断。

*编辑:澄清问题。