更新托管对象字段的领域变慢
Realm slow with updating managed object's field
我有一个相当简单的托管 Realm 对象 RealmAlertItem
,由一些字符串和浮点数组成。我有一个函数 showAlertNotification()
随后被调用(从网络外部触发),它依赖于上一次执行在下一次调用之前完全完成的事实。在这个函数中,我只更改了一个浮点字段(参见下面的 setHigh()
和 setLow()
)。如果两者都是 0,我删除该对象。
然而,似乎 Realm 无法及时更新对象,在第二次调用该函数时,对象仍然具有旧的 high
和 low
值。
这里是logcat:
08:47:04.180 D/debug: showAlertNotification(), guid: 58dfe381-b615-4ce0-beaf-5abb9b0733ac
08:47:04.185 D/debug: high 10000.0 , low 10800.0
08:47:04.205 D/debug: b // here we call RealmInstance.getThreadRealm().executeTransaction(realm1 -> alert.setHigh(0));
08:47:04.214 /debug: showAlertNotification(), guid: 58dfe381-b615-4ce0-beaf-5abb9b0733ac
08:47:04.215 /debug: high 10000.0 , low 10800.0 // here high should be 0!
08:47:04.224 /debug: d
如您所见,第二次调用在第一次调用之后发生得非常快(大约 30 毫秒后)。
代码如下:
private void showAlertNotification(RemoteMessage remoteMessage, String coinSlug, String coinName, Bitmap logo) {
Log.d("debug", "showAlertNotification(), guid: " + remoteMessage.getData().get("guid"));
RealmAlertItem alert = RealmInstance.getThreadRealm().where(RealmAlertItem.class).equalTo("guid", remoteMessage.getData().get("guid")).findFirst();
if(alert == null)
return;
... some work
// disable/delete this alert
if(!alert.isRepeating()) {
if (isHighLimit) {
if (alert.getLow() == 0) {
Log.d("debug", "a");
RealmInstance.getThreadRealm().executeTransaction(realm1 -> alert.deleteFromRealm());
} else {
Log.d("debug", "b");
RealmInstance.getThreadRealm().executeTransaction(realm1 -> alert.setHigh(0));
}
} else {
if (alert.getHigh() == 0) {
Log.d("debug", "c");
RealmInstance.getThreadRealm().executeTransaction(realm1 -> alert.deleteFromRealm());
} else {
Log.d("debug", "d");
RealmInstance.getThreadRealm().executeTransaction(realm1 -> alert.setLow(0));
}
}
}
Intent intent = new Intent("notifyAlertsChanged");
LocalBroadcastManager.getInstance(MainApplication.getAppContext()).sendBroadcast(intent);
}
如果需要,这是我的 RealmInstance Singleton:
public class RealmInstance {
private Realm realm;
private static RealmInstance realmInstance;
public static RealmInstance getInstance() {
if (realmInstance == null) {
realmInstance = new RealmInstance();
}
return realmInstance;
}
private RealmInstance() {
try {
realm = Realm.getDefaultInstance();
} catch (IllegalStateException err) {
init(MainApplication.getAppContext());
realm = Realm.getDefaultInstance();
}
}
public Realm getRealm() {
return realm;
}
public static Realm getThreadRealm() {
return Realm.getDefaultInstance();
}
public static void init(Context context) {
Realm.init(context);
RealmConfiguration config = new RealmConfiguration
.Builder()
.schemaVersion(13)
.deleteRealmIfMigrationNeeded()
.build();
Realm.setDefaultConfiguration(config);
}
}
我该如何解决这个问题?
您需要在 Application.java
中初始化您的 Realm 配置,并在需要时调用 Realm.getDefaultInstance()
(即摆脱您的单例 class)。
您还需要在使用后关闭 realm 实例,否则您在试验时会产生副作用,稍后您会遇到性能问题。
我有一个相当简单的托管 Realm 对象 RealmAlertItem
,由一些字符串和浮点数组成。我有一个函数 showAlertNotification()
随后被调用(从网络外部触发),它依赖于上一次执行在下一次调用之前完全完成的事实。在这个函数中,我只更改了一个浮点字段(参见下面的 setHigh()
和 setLow()
)。如果两者都是 0,我删除该对象。
然而,似乎 Realm 无法及时更新对象,在第二次调用该函数时,对象仍然具有旧的 high
和 low
值。
这里是logcat:
08:47:04.180 D/debug: showAlertNotification(), guid: 58dfe381-b615-4ce0-beaf-5abb9b0733ac
08:47:04.185 D/debug: high 10000.0 , low 10800.0
08:47:04.205 D/debug: b // here we call RealmInstance.getThreadRealm().executeTransaction(realm1 -> alert.setHigh(0));
08:47:04.214 /debug: showAlertNotification(), guid: 58dfe381-b615-4ce0-beaf-5abb9b0733ac
08:47:04.215 /debug: high 10000.0 , low 10800.0 // here high should be 0!
08:47:04.224 /debug: d
如您所见,第二次调用在第一次调用之后发生得非常快(大约 30 毫秒后)。
代码如下:
private void showAlertNotification(RemoteMessage remoteMessage, String coinSlug, String coinName, Bitmap logo) {
Log.d("debug", "showAlertNotification(), guid: " + remoteMessage.getData().get("guid"));
RealmAlertItem alert = RealmInstance.getThreadRealm().where(RealmAlertItem.class).equalTo("guid", remoteMessage.getData().get("guid")).findFirst();
if(alert == null)
return;
... some work
// disable/delete this alert
if(!alert.isRepeating()) {
if (isHighLimit) {
if (alert.getLow() == 0) {
Log.d("debug", "a");
RealmInstance.getThreadRealm().executeTransaction(realm1 -> alert.deleteFromRealm());
} else {
Log.d("debug", "b");
RealmInstance.getThreadRealm().executeTransaction(realm1 -> alert.setHigh(0));
}
} else {
if (alert.getHigh() == 0) {
Log.d("debug", "c");
RealmInstance.getThreadRealm().executeTransaction(realm1 -> alert.deleteFromRealm());
} else {
Log.d("debug", "d");
RealmInstance.getThreadRealm().executeTransaction(realm1 -> alert.setLow(0));
}
}
}
Intent intent = new Intent("notifyAlertsChanged");
LocalBroadcastManager.getInstance(MainApplication.getAppContext()).sendBroadcast(intent);
}
如果需要,这是我的 RealmInstance Singleton:
public class RealmInstance {
private Realm realm;
private static RealmInstance realmInstance;
public static RealmInstance getInstance() {
if (realmInstance == null) {
realmInstance = new RealmInstance();
}
return realmInstance;
}
private RealmInstance() {
try {
realm = Realm.getDefaultInstance();
} catch (IllegalStateException err) {
init(MainApplication.getAppContext());
realm = Realm.getDefaultInstance();
}
}
public Realm getRealm() {
return realm;
}
public static Realm getThreadRealm() {
return Realm.getDefaultInstance();
}
public static void init(Context context) {
Realm.init(context);
RealmConfiguration config = new RealmConfiguration
.Builder()
.schemaVersion(13)
.deleteRealmIfMigrationNeeded()
.build();
Realm.setDefaultConfiguration(config);
}
}
我该如何解决这个问题?
您需要在 Application.java
中初始化您的 Realm 配置,并在需要时调用 Realm.getDefaultInstance()
(即摆脱您的单例 class)。
您还需要在使用后关闭 realm 实例,否则您在试验时会产生副作用,稍后您会遇到性能问题。