Flutter 对象框性能问题
Flutter Objectbox performance issue
如果有人有解决办法,请帮助我。
现在我遇到了 ObjectBox 在 Flutter 中的性能问题。
我有 Event
Recurrence
EventPlace
的模型,每个模型都有关系。
问题是数据插入花费的时间太长,这会导致应用程序崩溃,因为操作在主线程中堆栈,直到完成它。
完成 1 个循环大约需要 300 毫秒...
我不知道该如何解决这个问题。我不应该使用模型之间的关系吗?
还是我使用 Objectbox 的方法不对?
[✓] Flutter (Channel stable, 1.22.5, on Mac OS X 10.15.7 19H524 darwin-x64, locale
en-GB)
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
[✓] Xcode - develop for iOS and macOS (Xcode 12.4)
[✓] Android Studio (version 4.1)
[✓] VS Code (version 1.54.3)
[✓] Connected device (1 available)
@Entity(uid: EVENT_UID)
class ObEvent {
@Id(assignable: true)
int id;
String deviceEventId;
String eventTitle;
String eventDesc;
String eventType;
List<String> eventLabels;
String timezone;
bool isAllDay;
String link;
int recurrId;
int originalRecurrId;
bool toDateUnfixed;
bool isOwned;
bool editable;
@Property(type: PropertyType.byteVector)
List<int> remainders;
@Index()
int calendarId;
@Index()
int parentId;
@Index()
String usersId;
@Index()
@Property(type: PropertyType.date)
DateTime eventPublishDate;
@Index()
@Property(type: PropertyType.date)
DateTime eventStart;
@Index()
@Property(type: PropertyType.date)
DateTime eventEnd;
@Index()
@Property(type: PropertyType.date)
DateTime createdAt;
@Index()
@Property(type: PropertyType.date)
DateTime updatedAt;
@Index()
bool deleted;
@Index()
bool notSynced;
final recurrence = ToOne<ObRecurrence>();
final place = ToOne<ObEventPlace>();
ObEvent({
this.id,
this.usersId,
this.calendarId,
this.eventTitle,
this.eventStart,
this.eventEnd,
this.deviceEventId,
this.editable,
this.eventType,
this.isAllDay,
this.toDateUnfixed,
this.eventDesc,
this.parentId,
this.eventLabels,
this.eventPublishDate,
this.link,
this.remainders,
this.recurrId,
this.originalRecurrId,
this.createdAt,
this.updatedAt,
this.isOwned = true,
this.deleted = false,
this.notSynced = false,
timezone,
}) : timezone = getIt<Vars>().defaultTimezone;
ObEvent.fromEvent(Event event)
: this.id = event.id,
this.usersId = event.userId,
this.calendarId = event.calendar.calId,
this.eventTitle = event.eventTitle,
this.eventStart = event.eventStart,
this.eventEnd = event.eventEnd,
this.deviceEventId = event.deviceEventId,
this.editable = event.editable,
this.eventType = EnumHandler.enumToString(event.eventType),
this.isAllDay = event.isAllDay,
this.toDateUnfixed = event.toDateUnfixed,
this.eventDesc = event.eventDesc,
this.parentId = event.parentId,
this.eventLabels = event.eventLabels,
this.eventPublishDate = event.eventPublishDate,
this.link = event.link,
this.remainders = event.remainders?.toList(),
this.recurrId = event.recurrId,
this.originalRecurrId = event.originalRecurrId,
this.isOwned = event.isOwned,
this.createdAt = event.createdAt,
this.updatedAt = event.updatedAt,
this.timezone = event.timezone;
ObEvent merge(ObEvent event) {
return ObEvent(
id: event.id ?? this.id,
usersId: event.usersId ?? this.usersId,
calendarId: event.calendarId ?? this.calendarId,
eventTitle: event.eventTitle ?? this.eventTitle,
eventStart: event.eventStart ?? this.eventStart,
eventEnd: event.eventEnd ?? this.eventEnd,
deviceEventId: event.deviceEventId ?? this.deviceEventId,
editable: event.editable ?? this.editable,
eventType: event.eventType ?? this.eventType,
isAllDay: event.isAllDay ?? this.isAllDay,
toDateUnfixed: event.toDateUnfixed ?? this.toDateUnfixed,
eventDesc: event.eventDesc ?? this.eventDesc,
parentId: event.parentId ?? this.parentId,
eventLabels: event.eventLabels ?? this.eventLabels,
eventPublishDate: event.eventPublishDate ?? this.eventPublishDate,
link: event.link ?? this.link,
remainders: event.remainders ?? this.remainders,
recurrId: event.recurrId ?? this.recurrId,
originalRecurrId: event.originalRecurrId ?? this.originalRecurrId,
isOwned: event.isOwned ?? this.isOwned,
createdAt: event.createdAt ?? this.createdAt,
updatedAt: event.updatedAt ?? this.updatedAt,
timezone: event.timezone ?? this.timezone,
deleted: event.deleted ?? this.deleted,
notSynced: event.notSynced ?? this.notSynced,
);
}
// For event type
EventType get type => eventType.toEnum(EventType.values);
set type(EventType value) => eventType = EnumHandler.enumToString(value);
}
@Entity(uid: EVENT_PLACE_UID)
class ObEventPlace {
@Id()
int id;
String address;
double lat;
double lon;
ObEventPlace({
this.id,
this.address,
this.lat,
this.lon,
});
ObEventPlace.fromEventPlace(EventPlace place)
: this.address = place.address,
this.lat = place.lat,
this.lon = place.lon;
ObEventPlace.fromMap(Map data)
: this.address = data['address'],
this.lat = data['lat'],
this.lon = data['lon'];
ObEventPlace merge(ObEventPlace ob) {
return ObEventPlace(
id: ob.id ?? this.id,
address: ob.address ?? this.address,
lat: ob.lat ?? this.lat,
lon: ob.lon ?? this.lon,
);
}
}
@Entity(uid: RECURRENCE_UID)
class ObRecurrence {
@Id(assignable: true)
int id;
String freq;
int intval;
List<String> byDay;
String timezone;
@Property(type: PropertyType.date)
DateTime dtStart;
@Property(type: PropertyType.date)
DateTime dtEnd;
@Property(type: PropertyType.byteVector)
List<int> byMonth;
@Property(type: PropertyType.byteVector)
List<int> byMonthDay;
@Property(type: PropertyType.byteVector)
List<int> setPositions;
@Property(type: PropertyType.byteVector)
List<int> exDates;
ObRecurrence({
this.id,
this.freq,
this.intval,
this.dtStart,
this.dtEnd,
this.byDay,
this.byMonth,
this.byMonthDay,
this.setPositions,
this.timezone,
this.exDates,
});
ObRecurrence.fromRecurr(Recurrence recurr)
: this.id = recurr.id,
this.freq = EnumHandler.enumToString(recurr.freq),
this.intval = recurr.intval,
this.dtStart = recurr.dtStart,
this.dtEnd = recurr.dtEnd,
this.byDay = recurr.byDay?.map((day) => EnumHandler.enumToString(day))?.toList(),
this.byMonth = recurr.byMonth?.toList(),
this.byMonthDay = recurr.byMonthDay?.toList(),
this.setPositions = recurr.setPositions?.toList(),
this.timezone = recurr.timezone,
this.exDates = recurr.exDates?.map((date) => date.millisecondsSinceEpoch)?.toList();
ObRecurrence merge(ObRecurrence rec) {
return ObRecurrence(
id: rec.id ?? this.id,
freq: rec.freq ?? this.freq,
intval: rec.intval ?? this.intval,
dtStart: rec.dtStart ?? this.dtStart,
dtEnd: rec.dtEnd ?? this.dtEnd,
byDay: rec.byDay ?? this.byDay,
byMonth: rec.byMonth ?? this.byMonth,
byMonthDay: rec.byMonthDay ?? this.byMonthDay,
setPositions: rec.setPositions ?? this.setPositions,
timezone: rec.timezone ?? this.timezone,
exDates: rec.exDates ?? this.exDates,
);
}
// For freq
Freq get frequency => freq.toEnum(Freq.values);
set frequency(Freq value) => EnumHandler.enumToString(value);
// For byDay field
Set<Day> get bydayList => byDay?.map((day) => day.toEnum(Day.values))?.toSet() ?? Set<Day>();
set bydayList(Set<Day> value) => byDay = value.map((day) => EnumHandler.enumToString(day)).toList();
// For exdates field
Set<DateTime> get exdates =>
exDates?.map((date) => DateTime.fromMillisecondsSinceEpoch(date))?.toSet() ?? Set<DateTime>();
set exdates(Set<DateTime> value) => exDates = value.map((date) => date.millisecondsSinceEpoch).toList();
MonthlyType get monthlyType => frequency == Freq.MONTHLY
? setPositions.isEmpty
? MonthlyType.BY_DATE
: MonthlyType.BY_WEEK_DAY
: MonthlyType.BY_DATE;
}
class Repository {
Store store;
Box<ObCalendar> _calBox;
Box<ObEvent> _eventBox;
Box<ObCalendarLink> _calLinkBox;
Box<ObTag> _tagBox;
Box<ObEventPlace> _placeBox;
CalendarRepository({
@required this.store,
}) : this._calBox = store.box<ObCalendar>(),
this._eventBox = store.box<ObEvent>(),
this._calLinkBox = store.box<ObCalendarLink>(),
this._tagBox = store.box<ObTag>(),
this._placeBox = store.box<ObEventPlace>(),
this._recBox = store.box<ObObRecurrence>();
cacheEvents(data, user) async {
final _obEvents = data.fold(<ObEvent>[], (prev, event) {
// This is the modal used in application and properties are the same with ObEvent class
final Event _event = Event.fromMap(user?.id, event);
final ObEvent _obOldEvent = _eventBox.get(_event.id) ?? ObEvent();
final ObEvent _obNewEvent = _obOldEvent.merge(ObEvent.fromEvent(_event))
..deleted = false
..notSynced = false;
// No update
if (_obOldEvent.id != null && (_event.updatedAt?.compareTo(_obNewEvent.updatedAt) ?? 0) == 0) {
return prev;
}
// Update place cache of event
if (_event.place != null) {
final ObEventPlace _oldPlace = _obNewEvent.place.target ?? ObEventPlace();
final ObEventPlace _newPlace = _oldPlace.merge(_oldPlace);
_placeBox.put(_newPlace);
_obNewEvent.place.target = _newPlace;
}
// Cache reucrrence if exists
if (_event.recurrence != null) {
final ObRecurrence _obOldRecurr = _obNewEvent.recurrence.target ?? ObRecurrence();
final ObRecurrence _obNewRecurr = _obOldRecurr.merge(ObRecurrence.fromRecurr(_event.recurrence));
_recBox.put(_obNewRecurr);
_obNewEvent..recurrence.target = _obNewRecurr;
}
prev.add(_obNewEvent);
return prev;
});
_eventBox.putMany(_obEvents);
}
}
临时我在其他线程中使用 compute
执行此操作以防止崩溃,但如果我真的可以获得基准文档所说的性能,我不需要这样做。
我看到的最大问题是在循环中执行许多写入操作 (put()
) 时没有使用 Transaction
。为此,请使用 Store.runInTransaction()
. Also, there is more information in ObjectBox-Java documentation 并且它也适用于 Dart。
简而言之,您可以将整个 cacheEvents()
包装在单个写入事务中,例如:
cacheEvents(data, user) => store.runInTransaction(TxMode.write, () {
// existing code
});
在那种情况下,你真的不需要使用 putMany(),它只是一个实用函数,如果你只插入一个“实体”,它会为你做交易。您可以在交易中使用纯 put()
。所以你的代码可能看起来像这样(未经测试,只是出于我的头脑):
cacheEvents(data, user) =>
store.runInTransaction(TxMode.write, () =>
data.forEach((event) {
// This is the modal used in application and properties are the same with ObEvent class
final Event _event = Event.fromMap(user?.id, event);
final ObEvent _obOldEvent = _eventBox.get(_event.id) ?? ObEvent();
final ObEvent _obNewEvent = _obOldEvent.merge(ObEvent.fromEvent(_event))
..deleted = false
..notSynced = false;
// No update
if (_obOldEvent.id != null && (_event.updatedAt?.compareTo(_obNewEvent.updatedAt) ?? 0) == 0) {
return;
}
// Update place cache of event
if (_event.place != null) {
final ObEventPlace _oldPlace = _obNewEvent.place.target ?? ObEventPlace();
final ObEventPlace _newPlace = _oldPlace.merge(_oldPlace);
_placeBox.put(_newPlace);
_obNewEvent.place.target = _newPlace;
}
// Cache reucrrence if exists
if (_event.recurrence != null) {
final ObRecurrence _obOldRecurr = _obNewEvent.recurrence.target ?? ObRecurrence();
final ObRecurrence _obNewRecurr = _obOldRecurr.merge(ObRecurrence.fromRecurr(_event.recurrence));
_recBox.put(_obNewRecurr);
_obNewEvent..recurrence.target = _obNewRecurr;
}
_eventBox.put(_obNewEvent);
}));
还有其他几个 suggestions/questions,虽然他们不会有这么大的影响:
- 考虑更改 .merge() 以实际更新
this
对象而不是创建新对象
- 考虑一下您是否需要所有这些索引:索引虽然有利于查询,但也会增加 insert/update 数据的时间,因为每个索引也需要更新。您是否对所有索引属性使用带条件的查询?
- 您也可以使用
eventBox.getMany()
首先获取您要接触的所有事件 - 虽然在这种情况下这可能不会对性能产生太大影响
顺便说一句,为什么您拥有所有这些“桥梁”类,例如 ObEvent
而不是将 Event
定义为 @Entity()
?很高兴知道是否可以在 ObjectBox 方面做一些事情,这样您就不必这样做了。
如果有人有解决办法,请帮助我。
现在我遇到了 ObjectBox 在 Flutter 中的性能问题。
我有 Event
Recurrence
EventPlace
的模型,每个模型都有关系。
问题是数据插入花费的时间太长,这会导致应用程序崩溃,因为操作在主线程中堆栈,直到完成它。
完成 1 个循环大约需要 300 毫秒...
我不知道该如何解决这个问题。我不应该使用模型之间的关系吗? 还是我使用 Objectbox 的方法不对?
[✓] Flutter (Channel stable, 1.22.5, on Mac OS X 10.15.7 19H524 darwin-x64, locale
en-GB)
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
[✓] Xcode - develop for iOS and macOS (Xcode 12.4)
[✓] Android Studio (version 4.1)
[✓] VS Code (version 1.54.3)
[✓] Connected device (1 available)
@Entity(uid: EVENT_UID)
class ObEvent {
@Id(assignable: true)
int id;
String deviceEventId;
String eventTitle;
String eventDesc;
String eventType;
List<String> eventLabels;
String timezone;
bool isAllDay;
String link;
int recurrId;
int originalRecurrId;
bool toDateUnfixed;
bool isOwned;
bool editable;
@Property(type: PropertyType.byteVector)
List<int> remainders;
@Index()
int calendarId;
@Index()
int parentId;
@Index()
String usersId;
@Index()
@Property(type: PropertyType.date)
DateTime eventPublishDate;
@Index()
@Property(type: PropertyType.date)
DateTime eventStart;
@Index()
@Property(type: PropertyType.date)
DateTime eventEnd;
@Index()
@Property(type: PropertyType.date)
DateTime createdAt;
@Index()
@Property(type: PropertyType.date)
DateTime updatedAt;
@Index()
bool deleted;
@Index()
bool notSynced;
final recurrence = ToOne<ObRecurrence>();
final place = ToOne<ObEventPlace>();
ObEvent({
this.id,
this.usersId,
this.calendarId,
this.eventTitle,
this.eventStart,
this.eventEnd,
this.deviceEventId,
this.editable,
this.eventType,
this.isAllDay,
this.toDateUnfixed,
this.eventDesc,
this.parentId,
this.eventLabels,
this.eventPublishDate,
this.link,
this.remainders,
this.recurrId,
this.originalRecurrId,
this.createdAt,
this.updatedAt,
this.isOwned = true,
this.deleted = false,
this.notSynced = false,
timezone,
}) : timezone = getIt<Vars>().defaultTimezone;
ObEvent.fromEvent(Event event)
: this.id = event.id,
this.usersId = event.userId,
this.calendarId = event.calendar.calId,
this.eventTitle = event.eventTitle,
this.eventStart = event.eventStart,
this.eventEnd = event.eventEnd,
this.deviceEventId = event.deviceEventId,
this.editable = event.editable,
this.eventType = EnumHandler.enumToString(event.eventType),
this.isAllDay = event.isAllDay,
this.toDateUnfixed = event.toDateUnfixed,
this.eventDesc = event.eventDesc,
this.parentId = event.parentId,
this.eventLabels = event.eventLabels,
this.eventPublishDate = event.eventPublishDate,
this.link = event.link,
this.remainders = event.remainders?.toList(),
this.recurrId = event.recurrId,
this.originalRecurrId = event.originalRecurrId,
this.isOwned = event.isOwned,
this.createdAt = event.createdAt,
this.updatedAt = event.updatedAt,
this.timezone = event.timezone;
ObEvent merge(ObEvent event) {
return ObEvent(
id: event.id ?? this.id,
usersId: event.usersId ?? this.usersId,
calendarId: event.calendarId ?? this.calendarId,
eventTitle: event.eventTitle ?? this.eventTitle,
eventStart: event.eventStart ?? this.eventStart,
eventEnd: event.eventEnd ?? this.eventEnd,
deviceEventId: event.deviceEventId ?? this.deviceEventId,
editable: event.editable ?? this.editable,
eventType: event.eventType ?? this.eventType,
isAllDay: event.isAllDay ?? this.isAllDay,
toDateUnfixed: event.toDateUnfixed ?? this.toDateUnfixed,
eventDesc: event.eventDesc ?? this.eventDesc,
parentId: event.parentId ?? this.parentId,
eventLabels: event.eventLabels ?? this.eventLabels,
eventPublishDate: event.eventPublishDate ?? this.eventPublishDate,
link: event.link ?? this.link,
remainders: event.remainders ?? this.remainders,
recurrId: event.recurrId ?? this.recurrId,
originalRecurrId: event.originalRecurrId ?? this.originalRecurrId,
isOwned: event.isOwned ?? this.isOwned,
createdAt: event.createdAt ?? this.createdAt,
updatedAt: event.updatedAt ?? this.updatedAt,
timezone: event.timezone ?? this.timezone,
deleted: event.deleted ?? this.deleted,
notSynced: event.notSynced ?? this.notSynced,
);
}
// For event type
EventType get type => eventType.toEnum(EventType.values);
set type(EventType value) => eventType = EnumHandler.enumToString(value);
}
@Entity(uid: EVENT_PLACE_UID)
class ObEventPlace {
@Id()
int id;
String address;
double lat;
double lon;
ObEventPlace({
this.id,
this.address,
this.lat,
this.lon,
});
ObEventPlace.fromEventPlace(EventPlace place)
: this.address = place.address,
this.lat = place.lat,
this.lon = place.lon;
ObEventPlace.fromMap(Map data)
: this.address = data['address'],
this.lat = data['lat'],
this.lon = data['lon'];
ObEventPlace merge(ObEventPlace ob) {
return ObEventPlace(
id: ob.id ?? this.id,
address: ob.address ?? this.address,
lat: ob.lat ?? this.lat,
lon: ob.lon ?? this.lon,
);
}
}
@Entity(uid: RECURRENCE_UID)
class ObRecurrence {
@Id(assignable: true)
int id;
String freq;
int intval;
List<String> byDay;
String timezone;
@Property(type: PropertyType.date)
DateTime dtStart;
@Property(type: PropertyType.date)
DateTime dtEnd;
@Property(type: PropertyType.byteVector)
List<int> byMonth;
@Property(type: PropertyType.byteVector)
List<int> byMonthDay;
@Property(type: PropertyType.byteVector)
List<int> setPositions;
@Property(type: PropertyType.byteVector)
List<int> exDates;
ObRecurrence({
this.id,
this.freq,
this.intval,
this.dtStart,
this.dtEnd,
this.byDay,
this.byMonth,
this.byMonthDay,
this.setPositions,
this.timezone,
this.exDates,
});
ObRecurrence.fromRecurr(Recurrence recurr)
: this.id = recurr.id,
this.freq = EnumHandler.enumToString(recurr.freq),
this.intval = recurr.intval,
this.dtStart = recurr.dtStart,
this.dtEnd = recurr.dtEnd,
this.byDay = recurr.byDay?.map((day) => EnumHandler.enumToString(day))?.toList(),
this.byMonth = recurr.byMonth?.toList(),
this.byMonthDay = recurr.byMonthDay?.toList(),
this.setPositions = recurr.setPositions?.toList(),
this.timezone = recurr.timezone,
this.exDates = recurr.exDates?.map((date) => date.millisecondsSinceEpoch)?.toList();
ObRecurrence merge(ObRecurrence rec) {
return ObRecurrence(
id: rec.id ?? this.id,
freq: rec.freq ?? this.freq,
intval: rec.intval ?? this.intval,
dtStart: rec.dtStart ?? this.dtStart,
dtEnd: rec.dtEnd ?? this.dtEnd,
byDay: rec.byDay ?? this.byDay,
byMonth: rec.byMonth ?? this.byMonth,
byMonthDay: rec.byMonthDay ?? this.byMonthDay,
setPositions: rec.setPositions ?? this.setPositions,
timezone: rec.timezone ?? this.timezone,
exDates: rec.exDates ?? this.exDates,
);
}
// For freq
Freq get frequency => freq.toEnum(Freq.values);
set frequency(Freq value) => EnumHandler.enumToString(value);
// For byDay field
Set<Day> get bydayList => byDay?.map((day) => day.toEnum(Day.values))?.toSet() ?? Set<Day>();
set bydayList(Set<Day> value) => byDay = value.map((day) => EnumHandler.enumToString(day)).toList();
// For exdates field
Set<DateTime> get exdates =>
exDates?.map((date) => DateTime.fromMillisecondsSinceEpoch(date))?.toSet() ?? Set<DateTime>();
set exdates(Set<DateTime> value) => exDates = value.map((date) => date.millisecondsSinceEpoch).toList();
MonthlyType get monthlyType => frequency == Freq.MONTHLY
? setPositions.isEmpty
? MonthlyType.BY_DATE
: MonthlyType.BY_WEEK_DAY
: MonthlyType.BY_DATE;
}
class Repository {
Store store;
Box<ObCalendar> _calBox;
Box<ObEvent> _eventBox;
Box<ObCalendarLink> _calLinkBox;
Box<ObTag> _tagBox;
Box<ObEventPlace> _placeBox;
CalendarRepository({
@required this.store,
}) : this._calBox = store.box<ObCalendar>(),
this._eventBox = store.box<ObEvent>(),
this._calLinkBox = store.box<ObCalendarLink>(),
this._tagBox = store.box<ObTag>(),
this._placeBox = store.box<ObEventPlace>(),
this._recBox = store.box<ObObRecurrence>();
cacheEvents(data, user) async {
final _obEvents = data.fold(<ObEvent>[], (prev, event) {
// This is the modal used in application and properties are the same with ObEvent class
final Event _event = Event.fromMap(user?.id, event);
final ObEvent _obOldEvent = _eventBox.get(_event.id) ?? ObEvent();
final ObEvent _obNewEvent = _obOldEvent.merge(ObEvent.fromEvent(_event))
..deleted = false
..notSynced = false;
// No update
if (_obOldEvent.id != null && (_event.updatedAt?.compareTo(_obNewEvent.updatedAt) ?? 0) == 0) {
return prev;
}
// Update place cache of event
if (_event.place != null) {
final ObEventPlace _oldPlace = _obNewEvent.place.target ?? ObEventPlace();
final ObEventPlace _newPlace = _oldPlace.merge(_oldPlace);
_placeBox.put(_newPlace);
_obNewEvent.place.target = _newPlace;
}
// Cache reucrrence if exists
if (_event.recurrence != null) {
final ObRecurrence _obOldRecurr = _obNewEvent.recurrence.target ?? ObRecurrence();
final ObRecurrence _obNewRecurr = _obOldRecurr.merge(ObRecurrence.fromRecurr(_event.recurrence));
_recBox.put(_obNewRecurr);
_obNewEvent..recurrence.target = _obNewRecurr;
}
prev.add(_obNewEvent);
return prev;
});
_eventBox.putMany(_obEvents);
}
}
临时我在其他线程中使用 compute
执行此操作以防止崩溃,但如果我真的可以获得基准文档所说的性能,我不需要这样做。
我看到的最大问题是在循环中执行许多写入操作 (put()
) 时没有使用 Transaction
。为此,请使用 Store.runInTransaction()
. Also, there is more information in ObjectBox-Java documentation 并且它也适用于 Dart。
简而言之,您可以将整个 cacheEvents()
包装在单个写入事务中,例如:
cacheEvents(data, user) => store.runInTransaction(TxMode.write, () {
// existing code
});
在那种情况下,你真的不需要使用 putMany(),它只是一个实用函数,如果你只插入一个“实体”,它会为你做交易。您可以在交易中使用纯 put()
。所以你的代码可能看起来像这样(未经测试,只是出于我的头脑):
cacheEvents(data, user) =>
store.runInTransaction(TxMode.write, () =>
data.forEach((event) {
// This is the modal used in application and properties are the same with ObEvent class
final Event _event = Event.fromMap(user?.id, event);
final ObEvent _obOldEvent = _eventBox.get(_event.id) ?? ObEvent();
final ObEvent _obNewEvent = _obOldEvent.merge(ObEvent.fromEvent(_event))
..deleted = false
..notSynced = false;
// No update
if (_obOldEvent.id != null && (_event.updatedAt?.compareTo(_obNewEvent.updatedAt) ?? 0) == 0) {
return;
}
// Update place cache of event
if (_event.place != null) {
final ObEventPlace _oldPlace = _obNewEvent.place.target ?? ObEventPlace();
final ObEventPlace _newPlace = _oldPlace.merge(_oldPlace);
_placeBox.put(_newPlace);
_obNewEvent.place.target = _newPlace;
}
// Cache reucrrence if exists
if (_event.recurrence != null) {
final ObRecurrence _obOldRecurr = _obNewEvent.recurrence.target ?? ObRecurrence();
final ObRecurrence _obNewRecurr = _obOldRecurr.merge(ObRecurrence.fromRecurr(_event.recurrence));
_recBox.put(_obNewRecurr);
_obNewEvent..recurrence.target = _obNewRecurr;
}
_eventBox.put(_obNewEvent);
}));
还有其他几个 suggestions/questions,虽然他们不会有这么大的影响:
- 考虑更改 .merge() 以实际更新
this
对象而不是创建新对象 - 考虑一下您是否需要所有这些索引:索引虽然有利于查询,但也会增加 insert/update 数据的时间,因为每个索引也需要更新。您是否对所有索引属性使用带条件的查询?
- 您也可以使用
eventBox.getMany()
首先获取您要接触的所有事件 - 虽然在这种情况下这可能不会对性能产生太大影响
顺便说一句,为什么您拥有所有这些“桥梁”类,例如 ObEvent
而不是将 Event
定义为 @Entity()
?很高兴知道是否可以在 ObjectBox 方面做一些事情,这样您就不必这样做了。