0

Here is my situation:

I have a chat app, which has a ListView of all the chats on the main screen. Each ListTile has widgets such as unread icons, chat title, etc. Currently, I have set it up so that these small widgets have their own query watcher to check when any data has changed and re-render accordingly.

However, one thing I have noticed is that even though my query watcher is pointed for a specific chat, it still executes if another completely unrelated chat is changed. This is some example code of what I mean:

final unreadQuery = chatBox.query(Chat_.guid.equals(controller.chat.guid)).watch();
sub = unreadQuery.listen((Query<Chat> query) {
  final chat = query.findFirst()!;
  if (chat.hasUnreadMessage != unread) {
    setState(() {
      unread = chat.hasUnreadMessage!;
    });
  }
});

So, even though the query is specifically where Chat_.guid.equals(controller.chat.guid), a completely unrelated chat update will still call the stream. This means that if one chat is unread, it will call the query findFirst() for the hundreds+ ListTiles that are in the view, even though their read status did not change. Is this bad for performance? Basically it seems like it would be spamming the database with hundreds of calls that are not needed.

Or is there a better way of doing this? One way I was thinking is to have a one singular query watcher, watching all the chats, and then have these widgets "subscribe" into this watcher with custom functions to filter out the data that they don't care about. Something like this:

chatBox.query().watch().listen((event) {
  final chats = event.find();
  for (Function f in _watcherFunctions) {
    f.call(chats);
  }
});

Here, the query will be called only once for any update for any chat, rather than a query called hundreds of times, however this time it is pulling in a lot more data because instead of fetching one chat it is fetching hundreds in one go. I am not sure which way is the best route to go, and would greatly appreciate any guidance. Thanks!

Tanay Neotia
  • 445
  • 3
  • 14
  • The behavior you describe is correct, see [API docs](https://pub.dev/documentation/objectbox/latest/objectbox/QueryBuilder/watch.html) (recently also in web [docs](https://docs.objectbox.io/data-observers-and-rx#flutter-dart)). A general question: where do the items of the list come from? Maybe use a single watcher there? Re performance: maybe only watch chats in view? Maybe switch to get instead of find inside the listener? – Uwe - ObjectBox Oct 24 '22 at 06:17
  • I see, thanks. One thing I'm not sure on: "Maybe switch to get instead of find inside the listener?" What do you mean by this? I don't see any `get` method on the query. – Tanay Neotia Oct 24 '22 at 14:27
  • I mean your code does not have to use the query inside the listener, it can also just use the box to get an object via ID (though that would have to be cached). – Uwe - ObjectBox Oct 25 '22 at 05:27
  • I assume box.get(id) is faster & better performing than executing the query? – Tanay Neotia Oct 25 '22 at 12:28
  • Yes, assuming speed and memory consumption is a concern. But as I said, it probably makes more sense to look into loading the whole list, passing a stream from watching a query to e.g. a StreamBuilder. – Uwe - ObjectBox Oct 26 '22 at 06:36

0 Answers0