B4J Question Does re-initializing a class not instantly kill all timers within?

Sandman

Expert
Licensed User
Longtime User
I have a class, lets call it OuterClass.

OuterClass have several other classes inited within it. Let's call them InnerClassA, InnerClassB and InnerClassC.

InnerClassA have a timer that manipulates a view in OuterClass.

While the app is running, I might re-initialize OuterClass. When I do this I get a crash. The crash is because the view wasn't available yet, which is as expected as the layout hasn't been loaded yet by OuterClass. What is surprising is the reason for why the view was even accessed: A timer in one of the inner classes produced a tick, and the _tick event sub tried to access the view.

I would have thought that all timers within a class (and the classes of its inner classes) would be instantly killed. Is this not correct?

Do I need to communicate to the whole class-tree "shut down your timers" and give them a grace period of a second before re-initing OuterClass?

B4X:
Error occurred on line: 216 (OuterClass)
java.lang.RuntimeException: Class instance was not initialized (MyCustomView)
    at anywheresoftware.b4a.debug.Debug.shouldDelegate(Debug.java:45)
    at b4j.example.MyCustomView._setnumber(MyCustomView.java:91)
    at b4j.example.outerclass._setnumber(outerclass.java:550)
    at b4j.example.innerclassa._debugtimer_tick(innerclassa.java:418)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:629)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:234)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:167)
    at jdk.internal.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:111)
    at anywheresoftware.b4a.shell.ShellBA.raiseEvent2(ShellBA.java:100)
    at anywheresoftware.b4a.objects.Timer$TickTack$1.run(Timer.java:135)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
    at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
    at java.base/java.lang.Thread.run(Thread.java:834)
 
Last edited:

EnriqueGonzalez

Well-Known Member
Licensed User
Longtime User
I would have thought that all times within a class (and the classes of its inner classes) would be instantly killed. Is this not correct?
No. Java kills an object when there is no way to call it again.

Having a timer running makes the GC think that it can still be called
 
Upvote 1

Sandman

Expert
Licensed User
Longtime User
Ok, thanks for the help.

(Still quite surprising for me that I have to do that, seems counter-intuitive somehow.)
 
Upvote 0
Top