Android Question B4XPages and ResumableSub

RB Smissaert

Well-Known Member
Licensed User
Longtime User
Just starting with B4XPages and noticed that ResumableSub is not behaving the same as in a non B4XPages project.
In an activity based project I can run this from Main with no problem:

B4X:
    Dim rs As ResumableSub = CSV2List(File.DirRootExternal & "/PhonePats", "menu_props2.csv", True, 44, 34, True, 10, -1)
    Wait For (rs) Complete (lstCSV As List)
    
    Log(lstCSV.Size)

and I can use the produced list fine.

In a B4XPages project though I get this error:
java.lang.ClassCastException: java.util.ArrayList cannot be cast to anywheresoftware.b4a.BA$ResumableSub

If I run this not as a ResumableSub:

B4X:
    Dim lstCSV As List
    
    lstCSV = CSV2List(File.DirRootExternal & "/PhonePats", "menu_props2.csv", True, 44, 34, True, 10, -1)

    Log(lstCSV.Size)

There is no problem.
Is this a known limitation of B4XPages or am I doing something wrong?

RBS
 

RB Smissaert

Well-Known Member
Licensed User
Longtime User
Correct me if I am wrong.
In this part of your code
B4X:
If bDone Then
      
        '----------
        'this works
        '----------
        Dim rs As ResumableSub = MakeMenuArray
        Wait For (rs) Complete (dDoneMenuArray As Boolean)
      
        '-----------------
        'this doesn't work
        '-----------------
'        MakeMenuArray

        For i = iButtonStartIndex To arrMenuButtons.Length - 1 'overflow button has no bitmap
            arrMenuButtons(i).SetBitmap(arrMenu(i).bmpIconBitMap1) '<<<<< java.lang.ArrayIndexOutOfBoundsException: length=0; index=0
        Next

    End If
after the MakeMenuArray you have a For cycle that need
B4X:
arrMenu(i).bmpIconBitMap1
to be ready. This is done by MakeMenuArray.
Calling MakeMenuArray as a normal Sub seems not to leave enough time to the Sub to complete its job before the next operations.
This is why using it as a Resumable Sub solve the problem.
As a confirmation, if you put a Sleep to let it complete
B4X:
If bDone Then
      
        '----------
        'this works
        '----------
'        Dim rs As ResumableSub = MakeMenuArray
'        Wait For (rs) Complete (dDoneMenuArray As Boolean)
      
        '-----------------
        'this doesn't work
        '-----------------
        MakeMenuArray
      
        Sleep(1000) 'Let us give time to MakeMenuArray to complete (exagerated value)
      
        For i = iButtonStartIndex To arrMenuButtons.Length - 1 'overflow button has no bitmap
            arrMenuButtons(i).SetBitmap(arrMenu(i).bmpIconBitMap1) '<<<<< java.lang.ArrayIndexOutOfBoundsException: length=0; index=0
        Next

    End If
then you can have your Sub like this
B4X:
Sub MakeMenuArray
    'Do things
    'More things
    'Yet more things
End Sub
But honestly I would prefer a Resumable Sub that just wait for the exact time needed by the Sub to complete.
Yes, thanks, that might be the problem.
Will try with the sleep, but as you say, a RemableSub seems better.

RBS
 
Upvote 0

rraswisak

Active Member
Licensed User
I would prefer using CallSubDelayed approach...

B4X:
    If bDone Then
        '...
        '...
        MakeMenuArray
        Wait For MakeMenuArray_Done Complete
        '...
        '...
    End If

B4X:
Private Sub MakeMenuArray
    'do all your code here and end with CallSubDelayed
    'If you want to return value, use CallSubDelayed2 or CallSubDelayed3 depend on your situation

    '...
    CallSubDelayed(Me,"MakeMenuArray_Done")
End Sub
 
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
I would prefer using CallSubDelayed approach...

B4X:
    If bDone Then
        '...
        '...
        MakeMenuArray
        Wait For MakeMenuArray_Done Complete
        '...
        '...
    End If

B4X:
Private Sub MakeMenuArray
    'do all your code here and end with CallSubDelayed
    'If you want to return value, use CallSubDelayed2 or CallSubDelayed3 depend on your situation

    '...
    CallSubDelayed(Me,"MakeMenuArray_Done")
End Sub
Where in your suggested code is the Boolean bDone coming from?
Did you mean:

B4X:
Private Sub MakeMenuArray() As Boolean

or does MakeMenuArray remain a ResumableSub?

RBS
 
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
Where in your suggested code is the Boolean bDone coming from?
Did you mean:

B4X:
Private Sub MakeMenuArray() As Boolean

or does MakeMenuArray remain a ResumableSub?

RBS
Sorry, ignore that, I thought that in my code the bDone came from MakeMenuArray.

RBS
 
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
No, just a normal sub.

Same approach for CSV2List sub too...
Just to make sure.
So, the end of CSV2List will be:

B4X:
    CallSubDelayed(Me, "CSV2List_Done")
    
    Return lstRows

End Sub

And that CSV2List will be called like this:

B4X:
    lstCSV = CSV2List(File.DirRootExternal & "/PhonePats", "menu_props2.csv", True, 44, 34, True, 10, -1)
    Wait For CSV2List_Done Complete

I am asking as it looks a bit strange to have the list before the Sub is done.

Also, could you tell why you prefer this approach?

RBS
 
Upvote 0

rraswisak

Active Member
Licensed User
B4X:
'...
'...
CSV2List(File.DirRootExternal & "/PhonePats", "menu_props2.csv", True, 44, 34, True, 10, -1)
Wait For CSV2List_Done Complete (lstCSV As List)
'...
'...

B4X:
Sub CSV2List(strFolder As String, _
             strFile As String, _
             bFileHasFieldNames As Boolean, _
             btSeparatorByte As Byte, _
             btEncloserByte As Byte, _
             bLookForEncloserByte As Boolean, _
             btEndOfLineByte As Byte, _
             lRows As Long)
     '...
     '...
     CallSubDelayed2(Me, "CSV2List_Done", lstRows)
End Sub

tell why you prefer this approach?
For me, its easier to define and controlled
 
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
B4X:
'...
'...
CSV2List(File.DirRootExternal & "/PhonePats", "menu_props2.csv", True, 44, 34, True, 10, -1)
Wait For CSV2List_Done Complete (lstCSV As List)
'...
'...

B4X:
Sub CSV2List(strFolder As String, _
             strFile As String, _
             bFileHasFieldNames As Boolean, _
             btSeparatorByte As Byte, _
             btEncloserByte As Byte, _
             bLookForEncloserByte As Boolean, _
             btEndOfLineByte As Byte, _
             lRows As Long)
     '...
     '...
     CallSubDelayed2(Me, "CSV2List_Done", lstRows)
End Sub


For me, its easier to define and controlled
OK, thanks.

BTW:

B4X:
Wait For CSV2List_Done Complete (lstCSV As List)

Should be:

B4X:
Wait For CSV2List_Done(lstCSV As List)

RBS
 
Upvote 0
Top