我已经阅读了有关在后台非 Looper 线程上保留长期Realm
实例的警告。我还看到有人建议快速打开和关闭Realm
实例不是最好的主意。鉴于这些约束(如果任何一个无效,请告诉我),我正在尝试确定将 Realm 与 websocket 一起使用的最佳方式,其中 websocket 事件包含需要访问Realm
的信息。
特别是,在这些选项(或完全其他选项)之间切换的正确方法是什么?
- 打开和关闭每个事件的
Realm
- 在线程开始时打开
Realm
,定期(每 30 秒左右)在线程上开始并提交事务以使 Realm 数据库保持最新状态。 - 为处理 websocket 消息的线程分配
Looper
。在线程上创建一次Realm
实例,并在线程的生存期内使其保持打开状态,使用Looper
使其保持最新状态。
其他值得注意的事情:
- 客户端已在 UI 线程上打开
Realm
。因此,据我了解,这意味着后台线程至少不需要支付架构验证的代价。 - 无法预测 websocket 事件的频率。在典型情况下,每秒的事件可能不超过一两个。但是,如果服务器上发生了更改一堆对象的大型操作,则客户端可能会相当快地收到数百或数千个 websocket 事件。
在每个事件上打开和关闭 Realm
就个人而言,根据那些说"他们的 Realm 已经过时"的人,我发现这是可靠的,所以这只有在你实际调用 refresh() 后才有意义Realm.getDefaultInstance()
.
在线程开始时打开 Realm,定期(每 30 秒左右)在线程上开始并提交事务,以使 Realm 数据库保持最新状态。
定期更新会导致不必要的事务,或者时不时地"不知道变化"。
另外,您实际上不需要提交事务来强制更新,因为beginTransaction()
已经将 Realm 数据库带到了新版本。
realm.beginTransaction();
realm.cancelTransaction();
这本身就足够了 - 但从技术上讲,这是一种解决方法,用于替换使用refresh()
(不是公共 API 的一部分),如果事务在另一个线程上打开,则还会阻塞线程。
为处理 websocket 消息的线程分配一个 Looper。在线程上创建一次 Realm 实例,并在线程的生命周期内保持打开状态,使用 Looper 使其保持最新状态。
如果您想始终确保当前线程始终可靠地保持最新状态,并且不会阻塞进程中的其他线程,那么这就是要走的路。
所以两种方式是:
1.) 保留一个只在事务中对 Realm 数据库进行查询的newSingleThreadedExecutor()
2.) 根据需要保持HandlerThread
活动状态,并在那里执行 Web 套接字 + 查询内容
(就我个人而言,我只在 RxJava +AndroidSchedulers.from(handlerThread.getLooper())
中使用过HandlerThread
)。