Calling functions from compute(info) vs (onUpdate), Defining Global Variables

Former Member
Former Member
Below is part of some code for a Data Field...
[Please note for some reason it would not allow me to post with many (but not all) brackets ( ) so I have had to delete them from the code and the text!!!]

using Toybox.WatchUi as Ui;
using Toybox.Graphics as Gfx;
using Toybox.System as Sys;
using Toybox.Lang as Lang;

class EDGEDataFieldView extends Ui.DataField {

var DistUnits;

function GetUnits {
return sys.getdevicesettings.distanceUnits.toNumber;
}

function compute info {
DistUnits = GetUnits;
if DistUnits == 1 {
AvgSpeed = Math.round info.averageSpeed * 22.3694;
} else {
AvgSpeed = Math.round info.averageSpeed * 36;
}
}

function onUpdate dc {
DistUnits = UserSettingsInfo.distanceUnits.toNumber;
}




I have found that I have to populate the DistUnits variable twice in the code and I have to do so in slightly different ways as you can see. If I call the GetUnits function from onUpdate it returns "method" instead of 0 or 1. And I cannot directly assign DistUnits within compute as both UserSettingsInfo.distanceUnits.toNumber() and sys.getdevicesettings().distanceUnits.toNumber() result in a Symbol Not Found Error or Unexpected Type Error respectively.

I understand (according to the notes in a new Data Field) that compute(info) is not guaranteed to be called prior to onUpdate so this means I would probably have to call twice anyway, or at least define a default value (other than null). What I don't understand is why I cannot call GetUnits from onUpdate (and why when I do or I don't call it at all I get "method"). Why is this so?

Also, it appears that my DistUnits variable is not global variable as if I don't assign a value in onUpdate, but do elsewhere, it fails its value is "method". Is it possible to define a truly global variable that can be assigned in one function and read in another? If so, how do I do this?
  • It's not clear what you're doing here. Your GetUnits function returns the system settings, yet in onUpdate, you're trying to get something from "UserSettingsInfo". Wouldn't you want to check distanceUnits from the system settings or the user settings, but not both places? (they might not be the same). Also, if in computer(), you've already done the math, why would you do it again in onUpdate()? Is UserSettingsInfo a class or an instance of a class?

    Then, this line:
    sys.getdevicesettings.distanceUnits.toNumber;

    has a couple things (one maybe due the edit you did to post). All you need is this (no toNumber() needed as it's already a number )
    sys.getdevicesettings().distanceUnits;

    Then you can compare that against sys.UNITS_STATUE or sys.UNITS_METRIC.

    Try posting without the code tags for now.

    Another thing to note is compute() is called every second, while onUpdate is only called every second when the DF is visible (it's on the current screen). And in compute, you want to null check averageSpeed before you use it, as it will be null until recording starts.
  • here's what I think you are trying to do. (untested code). I'm still not sure what UserSettingsInfo in your code is intended to be.

    It's a zip so there's no problem with posing any chars.


  • Former Member
    Former Member over 8 years ago
    Thanks Jim,

    Your code did compile and work as you expected and resolved my issue.

    And in compute, you want to null check averageSpeed before you use it, as it will be null until recording starts.

    I have already been checking the averageSpeed (and all other fields) is not null - I just left out most of the code as I did not see it as relevant to my question.

    I'm still not sure what UserSettingsInfo in your code is intended to be.

    I defined UserSettingsInfo as...
    UserSettingsInfo = Sys.getDeviceSettings();[/SIZE]
    ...so I was really just trying to skin the cat another way! The issue was that I had forgotten I could use the initialize function to help assign globally available variables/values and thus was trying to do so in both compute and onUpdate for no benefit. Clearly I still have plenty to learn!

    Thanks again!
  • One small thing to note in the code, is that while you can save the value in initialize, while your DF is running, it's possible that a user switches distance units between STATUTE and METRIC. Not a common thing though. The way to get around that, is if in compute() you do everything in metric, then in onUpdate() you do the conversion based on the current value of Sys.getDeviceSettings().distanceUnits (get it each time in onUpdate() and not in initialize() )