Differences in OnUpdate() behavior on watch face between devices (VA4/945)

I am trying to implement a partial update for my watchface. When I enter OnUpdate(), at the start of every minute I want to do a bunch of calculations that are fairly CPU intensive. In between that minute to the next minute I don't want to do anything and just keep the screen the same as before. Therefore I need a way to immediately exit OnUpdate(). I have implemented this by checking if the current clock time minute has changed, and if not I return immediately from OnUpdate() without calling dc.clear or View.onUpdate(dc). Therefore it shouldn't redraw any of the layout and it should keep things the same, right? That way if the user looks at their watch and triggers updates every second, OnUpdate() whill be called but it won't redraw anything, and it will just exit early and do nothing essentially.

Everything works in the simulator. The problem I'm having is that the actual behavior on a device differs. I have a 945 and a vivoactive 4 and they do different things and I don't know why. On the 945, the above process works correctly just as I described. On the VA4 however, my screen is cleared to black every time the early exit occurs. To make the matter worse, it appears OnUpdate() is always called twice when my face loads. For example if I scroll through the widget loop and then return to my watch face, I see everything draw correctly, and then less than a second later the screen flashes black, as though two OnUpdate() calls were made in rapid succession.

I'm not sure why the screen is getting cleared because I'm definitely not doing that myself. Does entering OnUpdate() always cause a screen draw/clear for some reason on a VA4 but not on a 945? I'm really confused about how to fix this and ensure it works on all devices.

I tried this code to see if had to do with transition animations. I added a 5 second delay before allowing the early return.

// Only allow early return 5 seconds after face has loaded
if( layoutTime != null && ( now.value() - layoutTime.value() ) > 5 ) { 
	if( isClosing || ( clockTime.min == lastMin && !newDataReceived ) ) {
		return;
	}
}
else {
	//It's a new minute or still less than 5 seconds after layout occurred
	//Do stuff
}

What I see is that the app draws correctly for the first 5 seconds after layout, and then immediately the screen goes black on the VA4 the first time it hits the return statement. Again this doesn't happen on the 945 and it continues to draw correctly.

  • Which SDK and what FW on the devices?

    One thing I don't see you mention is low power vs high power in the Watch face.  When in high power mode, onUpdate() is called every second.  Which mode you're in can be determined by onEnterSleep() and onExitSleep().  When a wf first starts on a device, it will be in high power mode and onUpdate() gets called every second, then drops into low power after a bit, go back to high power after a gesture, then drop back to low power after 10 seconds or so....  This is different that in the sim when under settings, you can turn low power on and off as you wish.

    I set/clear a boolean in onEnterSleep/onExitSleep so onUpdate knows the state it's in (only display seconds if inLowPower is false for example)..

    I suspect you're just got getting the chance to do the first display on a real device.  Just tried a test on a va4 where I have

    function onUpdate(dc) {

      if(!inLowPower) {return;}

    //otherwise do things and update the screen

    }

    And what I see is that the screen is blank (black) for a period of time (maybe 20 seconds) and then displays as it should (it's dropped back to low power), and if I move to a widget and back, same thing  blank for a bit, then normal). 

    BTW, this is something I wouldn't do, as in onUpdate you really want to always update the screen, for cases where the watch faces might be partially obscured by a message and doesn't fully restart.  What you could do is something like

    if(inLowPower) {doComplexStuff();}

    but always actually update the display

  • This is SDK 3.1. Devices are up to date with the latest FW. I am aware of the low/high power differences but I am currently not using that yet. I didn't want to use that as my mechanism for doing the calculations, because it will result in unnecessary code being ran. Part of the expensive calculations are drawing a graph of data to the display, point by point. The data only changes every 5 minutes (because I'm using a background http request) and therefore I only really need to draw the data once per 5 minutes because then it won't change until the next background temporal event. But it sounds like it doesn't work that way because I may need to update the display if the watch obscures part of it. I was thinking it maintained the buffer underneath notifications and restored that buffer, but perhaps that's not correct. I guess I will have to suffer the penalty of constantly drawing the display, but I don't like doing that in high power mode because it means I'm wasting battery life for drawing the data at unnecessary times. I suppose there is no way to save the display buffer and restore it, rather than redrawing the layout and everything?