Android Question MsgboxAsync in Resumable Sub

Alex_197

Well-Known Member
Licensed User
Longtime User
Hi all

I'm updating my app and replace all MsgBox that are depreciated to MsgBoxAsync.

I have a problem because MsgBoxAsync is not modal anymore

I have a code for example
B4X:
Private Sub ApplyServerResponse as Boolean

Dim TransferResult as String
TransferResult=GetParsedResultFromJSON ' Sub that takes response from the server JSON, pasrsed it and returns result

If TransferResult<>3 then
MsgBoxAsync("Transfer failed","Error")
return False
End If

'''
'Save Result into DB
Return True

End Sub

When transfer failed the MsgBoxAsync appears for a few seconds and the code doesn't stop like it used to be with MsgBox. So I modified my code to


B4X:
Private Sub ApplyServerResponse as Boolean

Dim TransferResult as String

TransferResult=GetParsedResultFromJSON ' Sub that takes response from the server JSON, pasrsed it and returns result

If TransferResult<>3 then

MsgBoxAsync("Transfer failed","Error")
Wait For MsgBox_Result(Res as Int)

if Res<>DialogResponse.Postitive then
Return False
end if


End If

'''

'Save Result into DB

Return True

End Sub

And now I have the error - Resumable subs return type must be ResumableSub (or none).

So what can I do? I can keep MsgBox but is there any other options?

I attached my small project.
 

Attachments

  • Test.zip
    10.7 KB · Views: 161

Peter Simpson

Expert
Licensed User
Longtime User
Well, it's all a bit of a mess really. You should really attach an example without the resumable sub errors and just exactly what your issue is.

Have you tried creating a blank project and just try the code below (which is copied and pasted from Erel's example within B4A)???

B4X:
    Msgbox2Async("Question?", "Title", "Yes", "Cancel", "No", Null, False)
    Wait For Msgbox_Result (Result As Int)
    If Result = DialogResponse.POSITIVE Then
     Log("Whatever...")
    End If

BTW you spelt Positive incorrectly, you wrote
B4X:
     if Res<>DialogResponse.Postitive then
 

Attachments

  • main.zip
    10.8 KB · Views: 160
Upvote 0

Alex_197

Well-Known Member
Licensed User
Longtime User
Well, it's all a bit of a mess really. You should really attach an example without the resumable sub errors and just exactly what your issue is.

Have you tried creating a blank project and just try the code below (which is copied and pasted from Erel's example within B4A)???

B4X:
    Msgbox2Async("Question?", "Title", "Yes", "Cancel", "No", Null, False)
    Wait For Msgbox_Result (Result As Int)
    If Result = DialogResponse.POSITIVE Then
     Log("Whatever...")
    End If

BTW you spelt Positive incorrectly, you wrote
B4X:
     if Res<>DialogResponse.Postitive then
This is a code from the blank project that I created
B4X:
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Private xui As XUI
End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
End Sub

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

Sub Activity_Resume
    If DoCheck Then
        Log("Ok")
    Else
        Log("Failed")
        Activity.Finish
    End If
End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub Button1_Click
    xui.MsgboxAsync("Hello world!", "B4X")
End Sub


private Sub DoCheck As Boolean
    Try

        Dim TransferResult As Int

        TransferResult=5

        If TransferResult<>3 Then
            MsgboxAsync("Transfer has failed","Error")
            Wait For MsgBox_Result(Res As Int)
           
            If Res<>DialogResponse.POSITIVE Then
                Return False
            End If
           
        Else
            Return True
        End If
       
    Catch
        Log(LastException)
        Return False
    End Try
End Sub

The main problem is that my app was created when MsgBox wasn't depreciated and it looks that now I need to rewrite a lot of code which I don't have a time to do,
 

Attachments

  • MsgBoxTest.zip
    9.2 KB · Views: 169
Last edited:
Upvote 0

Albert Kallal

Active Member
Licensed User
Ok, lets layout the "pattern" we have to deal with.

The challenge (or called it the "nasty") here is that when one introduces the async code, it will bite you becasue the calling routine NOW also has to deal with this problem. And REALLY nasty is this can force a bubble up of the problem to more then one level deep of sub calls you make. So, that REALLY is a challenge here.

But, lets take the basic pattern here. You have:

B4X:
Sub Button3_Click
   
    Dim MyResult As Boolean
    MyResult = DoStuff2
   Log(MyResult)

End Sub

Sub DoStuff2 As Boolean

   Msgbox("First message")
   Return False   

End Sub

So, ok, we change that msgbox in the DoStuff2 async, and we have to return a value.

The "nasty" is we NOW also have to modify the caller.

And golly - just exactly how much code you have (or want) to change, JUST because of that silly "async" problem!

And worse, the routine you using to call that code? You BETTER hope that it is not being called from another routine!

So you have basic example posted. And of course WHEN doing this, who wants to go an fix a WHOLE BUNCH of existing code you had working for years?

In other words, you don't want to re-think, and have to write (much) new code WHEN doing this change over.
It is not too bad. If you follow the "pattern" outlined, then it not too much code change, and MORE imporant, you don't have to much CHANGE the logic or thinking in your code. (you want to minmizine that re-writing, else you create new logic bugs - and that we REALLY want to avoid).

Once you get a "base" working pattern, you can quite much apply to the existing routines - and the changes should be minmial.

So we do this:

B4X:
Sub Button2_Click

   Dim MyResult As Boolean
  
   DoStuff   
   Wait For (DoStuff) Complete (MyResult As Boolean)
  
   Log(MyResult)

End Sub

Sub DoStuff As ResumableSub

    MsgboxAsync("First message","First")
    Wait For Msgbox_Result (Result As Int)
    Return True
......
End Sub

So just keep in mind:
You introduce the async msgbox, then you ALSO have to change/fix/update the caller routine.

With the above pattern/approach, then this issue is no too much change, and you don't rock the boat so to speak.

You JUST have to toss into this soup bowel that the CALLERS have to be changed.

So, change your code as above. The CALLER(S) need to be changed also (the wait for).

So, make (add) the async mesage box(s). Put the wait for after the msg box.

Then CHECK how many routines are calling WHAT you just changed.

You can hover your cursor over the sub name - then choose "find reference". You VERY much want to do this quick check. And if there is say 2, or 5 places that call the routine you just changed? You go and change the caller code in those 5 places. You often don't have to change the code, but if the sub is "returning" values like your case - then you have to change as per above. So, when you add the async boxes, do that find references as your last step - you NEED to check (look for) all the OTHER places in code that call/use that routine you JUST changed.

eg like this:
1617522569794.png


So in above, there is 2 places in code that I should check - and might have to change.

So, this is not too hard, but the "nasty" is when you make/add/change those msgbox(s) to async, then you have to check the CALLERS to that routine, and update those callers. As noted, in a lot of cases if you not return values - you are ok. But, no real way of avoiding this change for routines that return values AND you introduce async msgbox.

It always "sad" when you have to go start chopping up perfectly running code. But the above steps are not too bad. Get a test/working sample. Try it a few times, make sure it works. Then you get that cup of coffee, and try this on your production code. Do one routine first, check the "list" of callers. Try it.

If it works, then move on to the next routine that had some halting msgboxs.

I find that even for a relative large application, the change over is not bad. You NOT re-writing code, you NOT really changing the existing code base logic wise.

So the whole job, the whole task is more of a "refactoring" type of work - it a change, but not a difficult brain power one, since 99% of your existing code and logic can remain un-touched.

As noted, if the routine is called from some button etc., and it not returning values - just add the async msgbox. And in some cases you find this works REALLY nice, since in some cases you find that you don't need nor care or want the code to have waited anyway!

In other words? in some cases, you can pop up msgbox, but the code keeps on running and will finish up! Those are nice and fun, since then after they hit ok to dismiss the message, the code following the msgbox will have already completed!

But, to not break existing code flow? Don't worry about the above last cool pony magic trick!

Follow the above noted pattern. It is easy because you doing the SAME thing over and over to fix the code.
it will not take much time to change over your application.

But make no mistake - in those cases that you return values - you have to go and find ALL CALLERS throughout your WHOLE code base that calls that one routine. And since one is returning a value, then all of those callers need the wait for "Complete" with the "Result as "typevar" stub. This is a "nasty" and there is no way out of this task. But it is the "same" change over and over - it not a lot of brain power - but you do have to make this change.

Regards,
Albert D. Kallal
Edmonton, Alberta Canada
 
Upvote 0
Top