A constructor is invoked twice, how does it happen?

Hi, I met another problem just now.

My code is below.

---------------------app----------------------

using Toybox.Application;
using Toybox.WatchUi;

//golbal variable
class MyApp extends Application.AppBase {
	var myModel;
	var myDelegate;
    function initialize() {
        AppBase.initialize();
        myModel = new $.MyModel();
        myDelegate = new $.MyDelegate();
    }

    // onStart() is called on application start up
    function onStart(state) {
    }

    // onStop() is called when your application is exiting
    function onStop(state) {
    }

    // Return the initial view of your application here
    function getInitialView() {
        return [ new MyView(), myDelegate ];
    }
}

---------------------model----------------------
class MyModel {

    // Constructor
    function initialize() {
    	System.print("Model's constructor invoked");
        // initialize FIR filter
        var options = {:coefficients => [ -0.0278f, 0.9444f, -0.0278f ], :gain => 0.001f};
        try {
            mFilter = new Math.FirFilter(options);
            mLogger = new SensorLogging.SensorLogger({:enableAccelerometer => true});
            mSession = ActivityRecording.createSession({:name=>"Sport", :sport=>ActivityRecording.SPORT_GENERIC, :sensorLogger => mLogger});
        }catch(e) {
            System.println(e.getErrorMessage());
        }
        
        .......
}

---------------------delegate----------------------

class MyDelegate extends WatchUi.BehaviorDelegate {   
    var myModel;
    function initialize() {
        BehaviorDelegate.initialize();        
    	myModel=Application.getApp().myModel;
    }
    ........
}

---------------------delegate----------------------

class MyView extends WatchUi.View {
    function initialize() {
        View.initialize();
    }
    ........
}

Output is:

Background: Model's constructor invoked

Error: System Error

Details: Cannot create a new session while recording is active

Stack: 

  - initialize() at **/MyModel.mc:52 0x10001d84 

  - initialize() at **/MyApp.mc:10 0x10001998 

Model's constructor invoked

Obviously, the constructor is invoked twice, so weird???? 

Thanks a lot for any help.

  • Ok, I got it. I find menu2 supports a title that extends drawable, But it is just able to beautify the title, not the upper half screen.

  • And I'm pretty sure it won't update as you'd want to do with a time.

  • Sorry to jump in here, but I'll just point out the image (from 935) is not of the "clock time". It's the activity time from the activity pause menu of the 935, whose value doesn't change since the activity is paused. (Although the 935's pause menu does cycle between metrics, so the "title" or upper half of the screen is changing anyway).

    Also, why wouldn't you be able to dynamically update a Menu2 item or title on a regular basis? Couldn't you fire a timer which calls setTitle() or updateItem()?

    So either way I don't see why there's anything inherently impossible about displaying anything that changes as a Menu2 title, whether it's the clock time, activity time or a set of metrics. (The biggest problem seems to be that there's a very limited amount of space to draw anything in the title -- an actual metric with a label wouldn't fit)

    I modded the Menu2 sample in the SDK to produce this:

    It does seem that if you want something exactly like the image of the 935 activity pause menu that was posted, you'd have to write your own view. One place to start could be Dynamic Menu (https://github.com/flowstatedev/Dmenu). It's not perfect, but it's an implementation of a "menu" that you could mod for your own purposes.

  • While that may work in the sim, not sure about on a real device - Menu2 there is a native view.

  • While that may work in the sim, not sure about on a real device - Menu2 there is a native view.

    I don't see what that has to do with anything though. I realize that overriding Menu2.onUpdate() doesn't work (because it's a native view), but that's not what i'm doing anyway. (And I wouldn't expect that to work in either the sim or the real device.)

    If the Menu2 API provides a setTitle() method, then it should work whether it's fired based on user input, a timer callback or anything else.

    There's been other discussion about how other Menu2 methods may not be working properly (for add, removing or updating items), and I believe someone from the CIQ team agreed it was bug.

    The code I used is simply:

    - Fire timer every second

    - In timer callback, call Menu2.setTitle() and WatchUi.requestUpdate()

    I'll reiterate my stance that if the behavior of the simulator and real device can be so wildly divergent that you need obscure undocumented knowledge just to write an app, that's not a good thing.

    In this case, I would say that if Menu2 can't dynamically update as the documentation and simulator suggests, that's a bug. Why have setTitle() and updateItem() functions if they don't work?

    I know that updateItem() works for sure, as I've used it in a real app that runs on a real device. (I update a menu2 item based on user input in a submenu.)

  • I tried it on a real device and it doesn't work. My bad. Sorry for doubting you.

    Is WatchUi.requestUpdate() not expected to work on native views? Or is setTitle() broken? What's the point of having a setTitle() method if it won't work after the Menu2 has been created?

    Either way, it seems like an issue to me, especially when devs won't always have a device that supports all the features that they want to implement (e.g. on-device settings or data field alerts.)

  • I tried updating an item's sublabel dynamically, and it works on the real device, as I would expect (since I have a real app that updates a sublabel based on user input elsewhere).

    To me this (*) feels like a bug, native view notwithstanding. (* By "this" I mean the fact that setTitle() doesn't work dynamically, even though the docs and sim suggest that it does, and especially because updating an item does work dynamically)

    Sorry for the shakycam:

  • Native views in the sim can be a bit odd.  With Menu, it's just a generic representation, and when you use things like MapView/MapTrackView, it's quite different than on a real device.  That's a case where you really need to see how maps work on a real device to do a CIQ app.

  • setLabel/setSubLabel work fine on a real device.  I use them both in may things.

  • That doesn't really explain why updateItem() works but setTitle() doesn't.

    I'll just reiterate that not every hobbyist dev is willing or able to buy the latest CIQ watch just to do CIQ development.