Android Tutorial Using CallSubDelayed to interact between activities and services

Until Basic4android v2.00 the way to pass information between activities and services was through process global variables.

CallSubDelayed makes it much simpler. It allows you to call a sub in a different service or activity. If the target module is not active, then it will be started automatically. When the target module is ready, the sub will be called.

CallSubDelayed doesn't immediately call the target sub. It sends a message to the message queue. The internal framework manages this message and passes it to the target module when it is ready.

CallSubDelayed can also be used to call subs in the current module. It is useful in cases where you want to run some code "right after" the execution of some UI event.

Rules
- If the target module is already running then the sub will be called.
- If the target module is a service and it is not already running then it will first be started (Service_Create and Service_Start will first be executed).
The sub will be called after Service_Start.
- If the target module is an activity:
- If the application is visible (one of its activities is visible) then the target module will be started if needed and the sub will be called.
- If the application is in the background (can happen when a service calls an activity) then the message will be stored in a special message queue. In this case the sub will be called when the target activity becomes visible. The sub will be called before Activity_Resume.​

Just to make it clear, you do not need to call StartActivity or StartService when you use CallSubDelayed.
CallSubDelayed is the recommended method for interaction between activities and services.

Note that you cannot use CallSubDelayed (or CallSub) with code modules.
CallSubDelayed can be used with class instances. However the containing module will not be started if it is not already running.

An improved version of the two activities example:

B4X:
'Main Activity
Sub Process_Globals

End Sub

Sub Globals
   Dim Label1 As Label
End Sub

Sub Activity_Create(FirstTime As Boolean)
   Activity.LoadLayout("1")
End Sub

Sub Button1_Click
   'This call will bring Activity2 to front and will then execute ShowList
   CallSubDelayed2(Activity2, "ShowList", "This is the title")
End Sub
Sub GetResult(Result As String)
   Label1.Text = "You have chosen: " & Result
End Sub

'*****************************
'Activity2

Sub Process_Globals
   
End Sub

Sub Globals
   Dim ListView1 As ListView
End Sub

Sub Activity_Create(FirstTime As Boolean)
   Activity.LoadLayout("2")
   For i = 1 To 100
      ListView1.AddSingleLine("Item #" & i)
   Next
End Sub

Sub ShowList(Title As String)
   Activity.Title = Title
End Sub

Sub ListView1_ItemClick (Position As Int, Value As Object)
   'this call will bring Main to front and call GetResult
   CallSubDelayed2(Main, "GetResult", Value)
End Sub
 

Attachments

  • TwoActivities.zip
    7.2 KB · Views: 4,801

Derek Jee

Active Member
Licensed User
Longtime User
It will run before activity_resume.
Hi Erel

Mine is not playing nicely. I put the custom sub in where I populate a variable of the second activity from the parameter I pass from the first. I then run a sub from my activity_resume which should already have the populated variable which I use in subsequent subs. I put a log entry in on the custom sub and the activity_resume and the activity_resume runs first and not the way you suggested.. You can see the log entries state 1 and 2 in the order I think they should go but the log registers 2 first..

My sub looks like this
B4X:
Public Sub OpenFix(isTrue As Boolean)

    IsFix = isTrue
    Log("1 - " & IsFix)

End Sub

and my activity_resume is this

B4X:
Sub Activity_Resume

    Log("2 - " & IsFix)
    If IsFix = True Then
   
        LoadData
        Return

Etc

What am I going wrong?

Kind regards

Derek.
 

Derek Jee

Active Member
Licensed User
Longtime User
Here it is Erel..
 

Attachments

  • Test.zip
    1.9 KB · Views: 595

Derek Jee

Active Member
Licensed User
Longtime User
Load data is used to load persisted data in a database and must (also) be run from the activity resume.. I can do both I guess..

Thank you for your time Erel
 

Derek Jee

Active Member
Licensed User
Longtime User
I have a few activities which the user will switch between and need to save the data and load the data on switching. Where is a better place to load when opening/resuming an activity? I do call a sub to load the data from there, not just load the data from activity_resume..
 

LucaMs

Expert
Licensed User
Longtime User
I have a few activities which the user will switch between and need to save the data and load the data on switching. Where is a better place to load when opening/resuming an activity? I do call a sub to load the data from there, not just load the data from activity_resume..

If you load data calling a sub from Resume or you load data inside Resume, it is the same.

I think Resume is the right place.


[P.S. if you can load just the data changed it is better, of course]
 
Last edited:

ArminKH

Well-Known Member
I have discovered that I need to use CallSubDelayed to open subs from within Events that handle Gestures listeners, otherwise my app crashes sometimes. However, this causes my app to react slower. Can an idea be given what this delay is on average? My impression is that it is about 100 msec. Alternatively, I could use a timer, but I don't know to what interval I should set this timer, such that no crashes will occur with 100% certainty. Any recommendations?
Is using a timer principally a good idea (I have big doubts)?
It seems that for some properties the OS needs some more time to refresh the view(for example) before executing the next instruction.
Otherwise the next instruction is executed before the refresh
this is not relevant to b4a,this is how android works
 
Top