How to determine if a watchface is inside a view transition

The docs (https://developer.garmin.com/connect-iq/api-docs/Toybox/WatchUi/View.html#onUpdate-instance_method) say, that onUpdate may be called multiple times during view transition.

My watchface does make partial updates to increase it's performance but does make full updates at the very first layout and when it comes back from sleep. I would need to also find out if my view is inside a transition currently because I will need to make a full update in the first onUpdate after this transition, otherwise the full update will only be made current the transition and this leads to invalid displayed view...

Problem

Currently, if I start an app and then go back to my watchface, there is an animation with a semi transparent white overlay - in my partial updates I do not draw all parts of my watchface but rather one part after another and this means I can see this semi transparent white overlay from the transition until the corresponding area is redrawn

  • Thanks, that explains your suggestion.

    In my experience, I see partial overlaying notifcations only inside apps, the watchface is always overlayed by full screen notifications (but I can only speak for my F6X) - so the watchface is paused and resumed. I do make full redraws a few times after each onStart always, so I don't see problems there yet even though I'm using partial updates...

    I don't think that the screen redraws make a huge difference regarding power consumption although CPU time could be heavily spared with partial updates - but personally I don't care about this anyways.

    My problem with full redraws is just the huge delay when starting an app (~4s if onUpdate needs 100ms). Is there any other route I could go? I don't think there is much I can improve code wise anymore because of the many fonts I need to load inside each onUpdate. I assume the best alternative would be to draw everything to an offscreen buffer and make the partial updates on this buffer and reuse it - I tried this already but my watchface just has too many features and so there's not enough memory left for this solution.

  • If you are loading 20-30 fonts, you're hitting the file system for each one, and the file system on watches isn't that fast.

    You'll also see a lag if you tried to read a bunch of keys from Application.Storage (same thing - file system access).

    You'll probably keep seeing this unless you find a way to reduce the fonts you load at startup.

    And BTW, I have seen toasts that only cover part of the top of the screen - specifically when the watch starts up and it finds something like a Tempe sensor.

  • In the end it seems I must decide if I want a 100% safe watchface (that is slow) or a watchface that may sometimes have some visual bugs for a short time (but is faster).

    Being able to rotate the dc would solve all problems...

  • Hey , I'm struggling with this same situation in my own watchface development.  I can see the responses in the thread and I'm also hoping there's a way to do this efficiently.  Re-drawing the whole screen on every update, even if it's only once per minute, uses a lot more power than just doing partial updates in onUpdate().

    I currently have my code set to assign a clipping region over only the things that changed, and selectively updating the absolute minimum.  This means I always re-draw the time, and check if I need to update the battery info (only updated if the battery percent has changed by a whole-number amount) and/or weather info (only updated every set interval, user configurable between every minute all the way up to every 60 minutes).  I do a full redraw on the hour, as that's when more things may need updating (switching between AM/PM, new day of the week, etc).

    In my testing, this approach only has trouble when an overlaid system notification occurs -- phone connect/disconnect, new notification from phone, change in charging state.  When that happens, my code fails to re-draw the portion of the watchface that was obscured by the notification.  One solution would be to always redraw everything that exists in that portion of the watchface and selectively redraw everything else.  But I, too, wish there was a way to know when this was happening.  Let me know what you ended up doing with your watchface!

  • More info: according to the Simulator's profiler, my partial update strategy takes an average of 786us.  When I force the watchface to redraw every element every onUpdate(), it takes an average of 5776us -- more than 7x as much.  I really want this watchface to be as light on battery as possible!

  • My solution is simpler because my use case is simpler: I do draw one of each data field on my watchface that's expensive (I show 4 - 8 of those) every second - so after 8 seconds the whole screen is redrawn.

    I allow my users to disable this optimisation but I think most people accept this drawback - popups are not happening that often. Personally in my use case I don't care about it anymore, as I nearly never see it...

    Idee for you

    I think you can just redraw everything once when the screen switches from low power mode to high power mode (I have a setting to do this in my WF well) - regardless of the datas age. Maybe that's an acceptable compromise in your case...