Persistence Issue in Widgets

I'm seeing some weird behavior around whether the ObjectStore truly persists data in the case of widgets.

In cases where the widget times-out, I'm seeing the key persisted, so that on opening next opening of the widget, the value is there.

However, when pressing the back-button, in nearly all cases, the key is not persisted, meaning the on next opening of the widget, the data isn't there.

I looked at the `onBack` handler and noticed that I was doing:

function onBack() {
Ui.popView(Ui.SLIDE_IMMEDIATE);
return true;
}


which looks normal to me.

On a whim, I changed the code to

function onBack() {
return false;
}


and suddenly persistence works in nearly all cases.


My question is: is this expected behavior? Why is the `onBack` handler affecting persistence at all? At the very least, shouldn't that be more related to `onStop`?

Thoughts here?
  • Former Member
    Former Member over 8 years ago
    Widgets are not allowed to pop their initial view. It isn't well documented, but you should be seeing a crash report when you call popView() from the initial view of a widget. Since the app is crashing and not closing properly, data is not saved.

    The back key should probably not be getting passed to the initial widget view at all like with the next/previous behaviors that belong to the system at that level. We will look into making a change or improving documentation.
  • Okay that's really interesting and explains so much. Thanks!
  • Former Member
    Former Member over 8 years ago
    When I replied earlier, I forgot that the back key is not supposed to send any events to the delegate for the base view of a widget, so you actually should not be getting this onBack() call at all (at the base view).

    Can you let me know what device you saw this on? We should correct the device behavior.
  • When I replied earlier, I forgot that the back key is not supposed to send any events to the delegate for the base view of a widget, so you actually should not be getting this onBack() call at all (at the base view).

    Can you let me know what device you saw this on? We should correct the device behavior.


    I'm using a Vivoactive with latest firmware.

    Side-note;

    The fact that the widget default view is treated as special is a bit annoying, because in more complex widgets the 'home view' of the widget may change over time.

    For example, if a widget needs to perform any pairing operation, the default view might initially be a PairView, but then becomes a HomeView once paired. Now if back is pressed on the HomeView, it receives the onBack, and pops back to PairView. But we had performed a switchToView from PairView to HomeView, so it really should exit the widget! But -- and I'm guessing here -- since a widget default view is treated as special, a switchToView is actually treated like a pushView in this one case.

    The hack I think I'll have to employ is to hide multiple views inside a single WidgetView, where the widget view/delegate maintain state to know which 'real' view it should display. Then from the watches point of view, it sees a single view and onBack behaves normally.

    At this point, think I'm fighting against the SDK, but seems forced based on the current widget view mechanics.
  • No, switchToView() is not treated with a pushView() in this case. It simply swaps the current view on the view stack with the new view.
  • Former Member
    Former Member over 8 years ago
    Travis is correct. Using switchToView will replace your base view with the new view, and it will be treated the same as any other base view (the system widget controls are restricted). This is the only reasonable way for us to treat widgets. If the app was allowed to handle these controls at the base view, there would be no way to leave CIQ widgets.


    I've confirmed that the vivoactive does not block the back key press at the base view as it should and have filed a ticket with the device team to correct this behavior.
  • Travis is correct. Using switchToView will replace your base view with the new view, and it will be treated the same as any other base view (the system widget controls are restricted). This is the only reasonable way for us to treat widgets. If the app was allowed to handle these controls at the base view, there would be no way to leave CIQ widgets.


    I've confirmed that the vivoactive does not block the back key press at the base view as it should and have filed a ticket with the device team to correct this behavior.


    Hmm, I don't think this is the case, though I agree it should be. switchToView seems to work as advertised in all cases, except this one. What I mean, is that in practice, it behaves like pushToView in that a new view is changed to, however, pressing back doesn't cause the the app to exit, but rather go back to the previous view (which should have been popped before a change).


    In symbols:

    Widget Initial View: A

    Expected: A - switchToView -> B -> user-presses-back -> (exit)

    Observed: A - switchToView -> B -> user-presses-back -> A

    The observed behavior is exactly what we'd expect if switchToView was changed to pushView.
  • Disregard above; a test app I've made doesn't bear it out. Which is weird because I'm observing this behavior in a much more complex scenario, so perhaps there's a race going on somewhere...
  • ConnectIQ should not be subject to race conditions, all user code is executed in serial.

    Travis
  • You can spin up 'threads' using the Timer class, the code in the callback will be executed repeatedly at the interrupt interval, giving you thread-like, async behavior. This is how I do background note-syncing.

    If code in one of these callbacks changes the view out from under you, you can definitely experience race-like behavior (you thought you were one view, but now you're not).