Android Question Duplicated event runs haywire

Liew

Member
Licensed User
Longtime User
B4x page timer class:
Sub Class_Globals
    Private Root As B4XView 'ignore
    Private xui As XUI 'ignore
    Private cnt1 As Int
    Private tmr_test As Timer
End Sub

Public Sub Initialize As Object
    Return Me
End Sub

Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    
End Sub

Public Sub Start_TestTmr
   LogColor("Test timer started",Colors.Red)
   If (tmr_test.IsInitialized = False) Then
      tmr_test.Initialize("EventTmr", 500)
      tmr_test.Enabled = True
      cnt1 = 0
      Log("Timer is initialise")
   Else
       Log("Timer already initialised")
   End If
End Sub
Private Sub EventTmr_Tick
    cnt1 =cnt1 + 1
    If (cnt1 >10) Then
        tmr_test.Enabled = False
        cnt1 = 0
    End If
    Log("Event timer running "&cnt1)     
End Sub

B4x page trigger timer:
'Only code that use to trigger timer is inserted here'
Sub Class_Globals
    Private ats_test As DupTimer 'DupTimer is the B4xpage timer class'
End Sub
Private Sub Button_Click
  'To trigger the timer'
    If ("Test" = btn.Tag) Then
        ats_test.Initialize
        ats_test.Start_TestTmr
    End If
End Sub

Event log:
Test timer started
Timer is initialise
Event timer running 1
Event timer running 2
Event timer running 3
Event timer running 4
Test timer started
Timer is initialise
Event timer running 1
Event timer running 2
Event timer running 3
Event timer running 4
Event timer running 5
Event timer running 6
Event timer running 7
Event timer running 8
Event timer running 9
Event timer running 10
Event timer running 0
Event timer running 1
Event timer running 2
Event timer running 3
Event timer running 4
Event timer running 5
Event timer running 6
Event timer running 7
Event timer running 8
Event timer running 9
Event timer running 10
Event timer running 0
Event timer running 1
Event timer running 2
Event timer running 3
Event timer running 4
Event timer running 5
Event timer running 6
Event timer running 7
Event timer running 8
Event timer running 9
Event timer running 10
Event timer running 0
Event timer running 1
Event timer running 2
Event timer running 3
Event timer running 4
Event timer running 5
Event timer running 6
Event timer running 7
Event timer running 8
Event timer running 9
Event timer running 10
Event timer running 0
Event timer running 1
Event timer running 2
Event timer running 3
Event timer running 4
Event timer running 5
Event timer running 6


Can anyone help to look into the case above where a timer is created twice using the same B4x pages and why the event seems to crash and becomes uncontrolled. Is it B4x will not manage it as separate instance?
Thanks.
Regards,
Liew
 

JohnC

Expert
Licensed User
Longtime User
ChatGPT says...

From your description and the code snippets provided, it looks like your application is experiencing an issue with managing timer instances within a B4X application. The primary issue seems to stem from how timers are initialized and potentially re-initialized without properly managing their lifecycle. Here’s a breakdown of what's happening and how you might address it:

Understanding the Issue

  1. Multiple Initializations: When you call Start_TestTmr, it checks if tmr_test is initialized. If not, it initializes the timer and starts it. However, if this method is called again (e.g., upon another button click), and if the timer is still running or even if it's not, but hasn't been properly reset or disposed of, your log shows it being initialized again. This shouldn't normally happen since B4X's IsInitialized should prevent re-initialization if the timer object already exists.
  2. Event Log Confusion: The event log indicates that the timer starts over before the previous run finishes its count to 10 and then disables the timer. This could be due to multiple instances of DupTimer class being created and each having its own timer running concurrently. This is suggested by the repeated logs of "Test timer started" and "Timer is initialise", which indicate the Start_TestTmr is being called on separate instances.

Potential Solutions

  1. Single Instance Control: Ensure that only one instance of the DupTimer class is created and managed within your application. This might mean having a global variable or a singleton pattern to manage the creation and access to the DupTimer instance.
  2. Proper Timer Management: Modify the Start_TestTmr method to properly manage the timer lifecycle. If the timer is already running and you wish to restart it, you should first disable the current timer, reset its properties (if necessary), and then re-enable or re-initialize it.
  3. Debugging Tips:
    • Add more log statements to understand the flow, especially before and after timer initialization, and inside the click event that triggers the timer.
    • Verify that you are not inadvertently creating multiple instances of the DupTimer class each time a button is clicked.
Here’s a rough idea on how to adjust the Start_TestTmr to handle reinitialization better:
B4X:
Public Sub Start_TestTmr
   LogColor("Test timer started", Colors.Red)
   If tmr_test.IsInitialized = False Then
      tmr_test.Initialize("EventTmr", 500)
   End If
   tmr_test.Enabled = True ' Ensure timer is enabled regardless
   cnt1 = 0
   Log("Timer is set up")
End Sub
And ensure your button click or other mechanisms that initialize DupTimer do not create multiple instances unintentionally:
B4X:
' Ensure this method doesn't create multiple instances unintentionally
Private Sub Button_Click
    If "Test" = btn.Tag Then
        If ats_test = Null Then ' Initialize only if it hasn't been initialized
            ats_test.Initialize
        End If
        ats_test.Start_TestTmr
    End If
End Sub
These adjustments should help manage the timer more predictably and avoid the issue of duplicated event runs going haywire.

Also, the btn.Tag needs to be set to "Test" for the condition in the Button_Click event handler to be true and thus trigger the timer start logic. This setup is usually done in the part of your code where you initialize or configure your button, often in a method that sets up your UI elements. This could be within the B4XPage_Created method or another method that runs as part of your page's initialization process. Here's how you might do it:

B4X:
Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    ' Assuming you have a button named btnStartTest
    Dim btnStartTest As B4XView = Root.FindView("btnStartTest") ' Adjust according to your actual button name and method of finding it
    btnStartTest.Tag = "Test"
End Sub
This sets the Tag property of the button to "Test", which can then be used as a condition to trigger the timer start logic when the button is clicked. The Tag property is a convenient way to store additional information about a control or to identify controls without creating additional global variables.

Ensure you replace "btnStartTest" with the actual name or identifier used to find the button in your view hierarchy. The method of finding the button (Root.FindView) and the assignment might vary depending on your exact setup and whether you're using B4A, B4J, or B4i, as the specifics of UI element management can differ slightly between these platforms.
 
Last edited:
Upvote 0

Liew

Member
Licensed User
Longtime User
ChatGPT says...

From your description and the code snippets provided, it looks like your application is experiencing an issue with managing timer instances within a B4X application. The primary issue seems to stem from how timers are initialized and potentially re-initialized without properly managing their lifecycle. Here’s a breakdown of what's happening and how you might address it:

Understanding the Issue

  1. Multiple Initializations: When you call Start_TestTmr, it checks if tmr_test is initialized. If not, it initializes the timer and starts it. However, if this method is called again (e.g., upon another button click), and if the timer is still running or even if it's not, but hasn't been properly reset or disposed of, your log shows it being initialized again. This shouldn't normally happen since B4X's IsInitialized should prevent re-initialization if the timer object already exists.
  2. Event Log Confusion: The event log indicates that the timer starts over before the previous run finishes its count to 10 and then disables the timer. This could be due to multiple instances of DupTimer class being created and each having its own timer running concurrently. This is suggested by the repeated logs of "Test timer started" and "Timer is initialise", which indicate the Start_TestTmr is being called on separate instances.

Potential Solutions

  1. Single Instance Control: Ensure that only one instance of the DupTimer class is created and managed within your application. This might mean having a global variable or a singleton pattern to manage the creation and access to the DupTimer instance.
  2. Proper Timer Management: Modify the Start_TestTmr method to properly manage the timer lifecycle. If the timer is already running and you wish to restart it, you should first disable the current timer, reset its properties (if necessary), and then re-enable or re-initialize it.
  3. Debugging Tips:
    • Add more log statements to understand the flow, especially before and after timer initialization, and inside the click event that triggers the timer.
    • Verify that you are not inadvertently creating multiple instances of the DupTimer class each time a button is clicked.
Here’s a rough idea on how to adjust the Start_TestTmr to handle reinitialization better:
B4X:
Public Sub Start_TestTmr
   LogColor("Test timer started", Colors.Red)
   If tmr_test.IsInitialized = False Then
      tmr_test.Initialize("EventTmr", 500)
   End If
   tmr_test.Enabled = True ' Ensure timer is enabled regardless
   cnt1 = 0
   Log("Timer is set up")
End Sub
And ensure your button click or other mechanisms that initialize DupTimer do not create multiple instances unintentionally:
B4X:
' Ensure this method doesn't create multiple instances unintentionally
Private Sub Button_Click
    If "Test" = btn.Tag Then
        If ats_test = Null Then ' Initialize only if it hasn't been initialized
            ats_test.Initialize
        End If
        ats_test.Start_TestTmr
    End If
End Sub
These adjustments should help manage the timer more predictably and avoid the issue of duplicated event runs going haywire.

Also, the btn.Tag needs to be set to "Test" for the condition in the Button_Click event handler to be true and thus trigger the timer start logic. This setup is usually done in the part of your code where you initialize or configure your button, often in a method that sets up your UI elements. This could be within the B4XPage_Created method or another method that runs as part of your page's initialization process. Here's how you might do it:

B4X:
Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    ' Assuming you have a button named btnStartTest
    Dim btnStartTest As B4XView = Root.FindView("btnStartTest") ' Adjust according to your actual button name and method of finding it
    btnStartTest.Tag = "Test"
End Sub
This sets the Tag property of the button to "Test", which can then be used as a condition to trigger the timer start logic when the button is clicked. The Tag property is a convenient way to store additional information about a control or to identify controls without creating additional global variables.

Ensure you replace "btnStartTest" with the actual name or identifier used to find the button in your view hierarchy. The method of finding the button (Root.FindView) and the assignment might vary depending on your exact setup and whether you're using B4A, B4J, or B4i, as the specifics of UI element management can differ slightly between these platforms.
ChatGPT says...

From your description and the code snippets provided, it looks like your application is experiencing an issue with managing timer instances within a B4X application. The primary issue seems to stem from how timers are initialized and potentially re-initialized without properly managing their lifecycle. Here’s a breakdown of what's happening and how you might address it:

Understanding the Issue

  1. Multiple Initializations: When you call Start_TestTmr, it checks if tmr_test is initialized. If not, it initializes the timer and starts it. However, if this method is called again (e.g., upon another button click), and if the timer is still running or even if it's not, but hasn't been properly reset or disposed of, your log shows it being initialized again. This shouldn't normally happen since B4X's IsInitialized should prevent re-initialization if the timer object already exists.
  2. Event Log Confusion: The event log indicates that the timer starts over before the previous run finishes its count to 10 and then disables the timer. This could be due to multiple instances of DupTimer class being created and each having its own timer running concurrently. This is suggested by the repeated logs of "Test timer started" and "Timer is initialise", which indicate the Start_TestTmr is being called on separate instances.

Potential Solutions

  1. Single Instance Control: Ensure that only one instance of the DupTimer class is created and managed within your application. This might mean having a global variable or a singleton pattern to manage the creation and access to the DupTimer instance.
  2. Proper Timer Management: Modify the Start_TestTmr method to properly manage the timer lifecycle. If the timer is already running and you wish to restart it, you should first disable the current timer, reset its properties (if necessary), and then re-enable or re-initialize it.
  3. Debugging Tips:
    • Add more log statements to understand the flow, especially before and after timer initialization, and inside the click event that triggers the timer.
    • Verify that you are not inadvertently creating multiple instances of the DupTimer class each time a button is clicked.
Here’s a rough idea on how to adjust the Start_TestTmr to handle reinitialization better:
B4X:
Public Sub Start_TestTmr
   LogColor("Test timer started", Colors.Red)
   If tmr_test.IsInitialized = False Then
      tmr_test.Initialize("EventTmr", 500)
   End If
   tmr_test.Enabled = True ' Ensure timer is enabled regardless
   cnt1 = 0
   Log("Timer is set up")
End Sub
And ensure your button click or other mechanisms that initialize DupTimer do not create multiple instances unintentionally:
B4X:
' Ensure this method doesn't create multiple instances unintentionally
Private Sub Button_Click
    If "Test" = btn.Tag Then
        If ats_test = Null Then ' Initialize only if it hasn't been initialized
            ats_test.Initialize
        End If
        ats_test.Start_TestTmr
    End If
End Sub
These adjustments should help manage the timer more predictably and avoid the issue of duplicated event runs going haywire.

Also, the btn.Tag needs to be set to "Test" for the condition in the Button_Click event handler to be true and thus trigger the timer start logic. This setup is usually done in the part of your code where you initialize or configure your button, often in a method that sets up your UI elements. This could be within the B4XPage_Created method or another method that runs as part of your page's initialization process. Here's how you might do it:

B4X:
Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    ' Assuming you have a button named btnStartTest
    Dim btnStartTest As B4XView = Root.FindView("btnStartTest") ' Adjust according to your actual button name and method of finding it
    btnStartTest.Tag = "Test"
End Sub
This sets the Tag property of the button to "Test", which can then be used as a condition to trigger the timer start logic when the button is clicked. The Tag property is a convenient way to store additional information about a control or to identify controls without creating additional global variables.

Ensure you replace "btnStartTest" with the actual name or identifier used to find the button in your view hierarchy. The method of finding the button (Root.FindView) and the assignment might vary depending on your exact setup and whether you're using B4A, B4J, or B4i, as the specifics of UI element management can differ slightly between these platforms.
Hi JohnC,
Thank you so much for your reply with such a detailed explanation.
It is concluded from the test program that B4X cannot handle multiple instances and only ONE instance should be created.
Unlike in Visual Studio C language where we actually call a module several times and each time it is created it runs on a separate code space. In this case I am referring to code like client socket handling. The same code is run to handle a new client connection. Pardon me if I am comparing something between C and B4x illogically.
Basically, what I wanted to know is how B4x handle multiple instances.
Thanks.
Regards,
Liew
 
Upvote 0

Liew

Member
Licensed User
Longtime User
Can you upload a small project that reproduces it?
Hi Erel,
My post was replied, and basically I am testing how B4x handle duplicate instance.
It seems that if an instance is created twice, it will not be handle in separate code space and multiple event created are not handled.
Thanks.
Regards,
Liew
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
It seems that if an instance is created twice, it will not be handle in separate code space and multiple event created are not handled.
Android apps are not supposed to run multiple times.
Only one instance of an app can run at a time on an android device.

What exactly are you trying to archieve?
 
Upvote 0

Liew

Member
Licensed User
Longtime User
Android apps are not supposed to run multiple times.
Only one instance of an app can run at a time on an android device.

What exactly are you trying to archieve?
Hi Don,

I didn't know about android app architecture much and how instances are handled.
Pardon me for posting questions about these and if it appeared disturbing then I felt very sorry about it.
Thanks.
Regards,
Liew
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
timer is created twice using the same B4x pages
The problem is that you seem to be initializing the same B4Xpages class multiple times. That's a no-no. Also, if you have a class with a timer and you initialize a new instance of that class, each instantiation of that class will have its own timer. So yes, in your case you are creating timer after timer and may, after some point, run out of resources.
 
Upvote 0
Top