Android Question How can I load a new layout stopping sub in process

LuisFP

Member
Licensed User
I want that with a Activity.LoadLayout, sub in process finished. In the code below, extract from tutorial of "Different examples with 2 layouts" for TwoActivityLayouts, I add a button1 and Label1 in TwoLayouts1. Button1 write in loop with sleep on Label1. If I click in btnNext1, TwoLayouts2 is load. But when click in btnNext2 and TwoLayouts1 is load, the loop initiated by button1 is still active and writing. There are any way to stop sub in process when you load a new layout?

I test that if I use 2 activities (following the same tutorial) and use Activity.Finish before StartActivity(Layout2) this stop sub, but in fact I have a 4 Layouts with a common code and I prefer (if is possible) not to use several activities. (Following LoadLayoutToPanel example not stop sub)

Thanks

Tutorial: https://www.b4x.com/android/forum/threads/different-examples-with-2-layouts.8416/
LoadLayoutToPanel: https://www.b4x.com/android/forum/threads/how-do-i-unload-a-layout.6993/


B4X:
'Activity module
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.

    Dim btnNext1, btnNext2 As Button
    Dim edtText1, edtText2 As EditText
    Dim rbtTest1, rbtTest2 As RadioButton
    Dim Label1 As Label
End Sub

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

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub btnNext1_Click
    Activity.RemoveAllViews
    Activity.LoadLayout("TwoLayouts2")
End Sub

Sub btnNext2_Click
    Activity.RemoveAllViews
    Activity.LoadLayout("TwoLayouts1")
End Sub

Sub Button1_Click
    For i=1 To 30
        Label1.Text="Hello"
        Sleep(1000)
        Label1.Text="World"
        Sleep(1000)
        Label1.Text="No Stop"
        Sleep(1000)
    Next
End Sub
 

Erel

Administrator
Staff member
Licensed User
The way to solve such cases is with a global "index" variable that you check after each Sleep or Wait For call:

B4X:
Sub Button1_Click
    ButtonIndex = ButtonIndex + 1 'ButtonIndex is a process global int
    Dim MyIndex = ButtonIndex
    For i=1 To 30
        Label1.Text="Hello"
        Sleep(1000)
        If ButtonIndex <> MyIndex Then Return
        Label1.Text="World"
        Sleep(1000)
        If ButtonIndex <> MyIndex Then Return
        Label1.Text="No Stop"
        Sleep(1000)
        If ButtonIndex <> MyIndex Then Return
    Next
End Sub

'stopping the loop when you load layout:
Sub btnNext2_Click
    Activity.RemoveAllViews
    Activity.LoadLayout("TwoLayouts1")
    ButtonIndex = ButtonIndex + 1
End Sub
 

LuisFP

Member
Licensed User
Well, I was using something similar, with a binary global variable but I was just wondering if there was anything better.

Thank you
 

MarkusR

Well-Known Member
Licensed User
its better to use a timer and set the label text in the tick event.
executed events should not hang in a loop purposely.
this sleep cares the event system that it continues before the click event is finished.
and i think because this Button1 is not disabled you can click again and again what cause chaos.
 

LuisFP

Member
Licensed User
In fact the loop is only for an example effect.
In the real app there are not a loop but there are several sleeps each one after show something for a animated tutorial propose.
So if user click on other menu item during animated tutorial, when a new layout is load I need that animated tutorial finish.
 

MarkusR

Well-Known Member
Licensed User
A timer is not better than using Sleep.
The code I posted is a good way to deal with such cases.
the tick event can just change new label caption and the event exists. no need for a loop and delay & waits inside a sub.
in this case of animated layout maybe i would also use a sequence in one sub.

B4X:
Sub Process_Globals
    Private MainForm As Form
    
    Private Label1 As Label
    Private Button1 As Button

    Private Timer1 As Timer
    Private LabelIndex As Int = 0
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.RootPane.LoadLayout("Layout1") 'Load the layout file.

    MainForm.Show
    
    Timer1.Initialize("Timer1",1000)

End Sub

Sub Timer1_Tick
    
    LabelIndex = LabelIndex + 1
        
    Select LabelIndex
        Case 1
            Label1.Text="Hello"
        Case 2
            Label1.Text="World"
        Case 3
            Label1.Text=":)"
            LabelIndex = 0
    End Select
    
End Sub

Sub Button1_Click
    
    Timer1.Enabled = Not (Timer1.Enabled)
    If Timer1.Enabled = False Then Label1.Text = ":("
    
End Sub
 
Top