B4A Class [B4X] CallSubPlus - CallSub with explicit delay

In many cases you need to run a task in a few seconds. The solution for such cases is to create a timer and then execute the task in the timer's Tick event. This is good for a single task. However if you need to run multiple tasks then it becomes difficult to maintain.

This small class makes it much simpler. You just need to call CallSubPlus with the target sub and the delay.
Internally it uses a (one shot) timer together with CallSubDelayed or CallSub.

There are four methods:
CallSubPlus, CallSubPlus2, CallSubDelayedPlus and CallSubDelayedPlus2.
CallSubPlus and CallSubDelayedPlus should be used with subs with no parameters. The others should be used with subs with a single parameter. The parameter type must be an array of objects.

For example:
Sub Activity_Click
   Log($"Click: $Time{DateTime.Now}"$)
   Starter.csu.CallSubPlus(Me, "Sub_1", 2000) 'run in two seconds
   Starter.csu.CallSubPlus2(Me, "Sub_2", 1000, Array("Value 1", "Value 2")) 'run in one second
End Sub

Sub Sub_1
   Log($"Sub_1: $Time{DateTime.Now}"$)
End Sub

Sub Sub_2(args() As Object)
   Log($"Sub_2: $Time{DateTime.Now}, arg(0)=${args(0)}"$)
End Sub

csu is declared in the Starter service:
Sub Process_Globals
   Public csu As CallSubUtils
End Sub

Sub Service_Create
End Sub


- Make sure to include an underscore in the target subs names if you intend to compile with obfuscation.
- CallSubDelayed will start the target service or activity if needed (see this tutorial for more information: https://www.b4x.com/android/forum/t...etween-activities-and-services.18691/#content).
- You can safely call multiple subs. This can be useful to break a long task into smaller tasks.
- This class can also be used with B4i and B4J.
- Add this class to your project with Project - Add Existing Module.


  • CallSubUtils.bas
    2.5 KB · Views: 1,206


Active Member
Licensed User
I had the "If rdd.Delayed Then" in tmr_Tick give an error. Checked this sub and found it wasn't Initialized
Private Sub PlusImpl(Module As Object, SubName As String, Delay As Int, Arg() As Object, delayed As Boolean)
    If RunDelayed.IsInitialized = False Then RunDelayed.Initialize
    Dim tmr As Timer
    tmr.Initialize("tmr", Delay)
    Dim rdd As RunDelayedData
    rdd.Initialize ' added 2/18/2018 not initialized
    rdd.Module = Module
    rdd.SubName = SubName
    rdd.Arg = Arg
    rdd.delayed = delayed
    RunDelayed.Put(tmr, rdd)
    tmr.Enabled = True
End Sub
Last edited: