As you learned before, using loops will avoid code repetition and it can be a very efficient way to get things done.
However, if not handled properly, they do also hold the danger of freezing your entire app and/or causing an ANR warning.
Caution level:
Safety:
Efficiency:
However, if not handled properly, they do also hold the danger of freezing your entire app and/or causing an ANR warning.
Caution level:
1. The least "dangerous" kind of loop is the For...Next loop, because in principle it will "always end".
Consider the following code:
Depending on the hardware, this example will indeed take some (maybe a lot of) time to complete, but nevertheless we can rest assured it will (eventually) complete.
2. The Do While/Until...Loop cycle should be regarded as a more "dangerous" kind of loop and has be used more responsibly.
This loop should end in a few seconds (minutes? hours?), but who knows, it might run forever. This kind of approach is not advisable at all.
Consider the following code:
B4X:
'This code will most probably cause an ANR.
For i = 0 to 999999
If File.Exists(File.DirAssets, i & ".txt") Then Log("True")
Next
2. The Do While/Until...Loop cycle should be regarded as a more "dangerous" kind of loop and has be used more responsibly.
B4X:
'This code will most probably cause an ANR.
Do Until n = 14
Dim n = Rnd(0, 9999999999) As Long
Loop
Safety:
If you really have to use a "dangerous" loop in your app, a good practice would be implementing a timeout. Basically, exit the loop if it starts taking too long.
This way you will always ensure that there will be an exit point in your loop. Optionally you may handle the timeout after you exit the loop. Here's how:
B4X:
Dim loopTimeout = 10000 '(ms) = 10 seconds
Dim loopStart = DateTime.Now As Long
Do (Until n = 14) Or (DateTime.Now - loopStart >= loopTimeout)
Dim n = Rnd(0, 999999) as Int
Loop
B4X:
Dim timeoutError = False As Boolean
Dim loopTimeout = 10000 '(ms) = 10 seconds
Dim loopStart = DateTime.Now As Long
Do Until n = 14 _
Or timeoutError
Dim n = Rnd(0, 999999) as Int
If (DateTime.Now - loopStart >= loopTimeout) Then timeoutError = True
Loop
If timeoutError Then
Log("Sorry, bla bla bla...")
...
End If
Efficiency:
Not only you can apply the safety device described above, you can as well add some efficiency oriented instructions to your code. For this matter, we will use the Continue and Exit instructions.
In the example below, the Exit statement will terminate the For loop once the correct file is found.
...and here's a way to exit nested loops:
The Continue statement will ignore all the loop code bellow and proceed to the next iteration:
Of course, the same could be achieved with the traditional If/Then/Else statements but it's good to know we can also do it this way.
Long-story short: The Exit statement exits the whole loop. The Continue statement exits the current iteration.
In the example below, the Exit statement will terminate the For loop once the correct file is found.
B4X:
'Find and process ONLY the most recent yearly report.
For i = 2015 to 1977 Step -1
If File.Exists(File.DirAssets, "year_report_" & i & ".txt" Then
...
...
...
...
Exit
End if
Next
B4X:
For i = 0 to 100
For j = 0 to 100
If a(i, j) = "GOLD" Then Exit
...
...
...
Next
If a(i, j) = "GOLD" Then Exit
Next
Log("Gold was found in [A] at" & i & ", " & j)
The Continue statement will ignore all the loop code bellow and proceed to the next iteration:
B4X:
'Do not process ADMIN users
For i = 0 to (users.Lenght - 1)
If users(i) = "ADMIN" Then Continue 'at this point the current iteration is terminated and the loop proceeds to the next one.
...
...
...
...
...
...
...
Next
Long-story short: The Exit statement exits the whole loop. The Continue statement exits the current iteration.
Last edited: