Android Tutorial [B4X] OkHttpUtils2 with Wait For

Discussion in 'Tutorials & Examples' started by Erel, May 9, 2017.

Thread Status:
Not open for further replies.
  1. Erel

    Erel Administrator Staff Member Licensed User



    Downloading resources is simpler with the new Resumable Subs feature.

    Using Wait For we can wait for the JobDone event in the same sub that started the download.
    No longer is it needed to have a single sub that handles all requests results.

    Simplest example:
    Code:
    Dim j As HttpJob
    j.Initialize(
    "", Me)
    j.Download(
    "https://www.google.com")
    Wait For (j) JobDone(j As HttpJob)
    If j.Success Then
       
    Log(j.GetString)
    End If
    j.Release

    Example of downloading a quote from a quotes service:
    Code:
    Sub DownloadQuote
       
    Dim j As HttpJob
       j.Initialize(
    "", Me) 'name is empty as it is no longer needed
       j.Download("http://quotesondesign.com/wp-json/posts?filter[orderby]=rand")
       
    Wait For (j) JobDone(j As HttpJob)
       
    If j.Success Then
         
    'The result is a json string. We parse it and log the fields.
         Dim jp As JSONParser
         jp.Initialize(j.GetString)
         
    Dim quotes As List = jp.NextArray
         
    For Each quot As Map In quotes
           
    Log("Title: " & quot.Get("title"))
           
    Log("Content: " & quot.Get("content"))
         
    Next
       
    End If
       j.Release
    End Sub
    Note that the HttpJob object is a local variable. This is the recommended way to create HttpJobs as it allows us to set the sender filter parameter (read more in the tutorial about resumable subs).
    The same sub can be called multiple times and also other subs that send HttpJobs. As each HttpJob is unique, all the events will reach the correct place.

    Downloading two resources, one after another:
    Code:
    Sub DownloadTwoLinks
       
    Dim j As HttpJob
       j.Initialize(
    "", Me) 'name is empty as it is no longer needed
       j.Download("https://www.google.com")
       
    Wait For (j) JobDone(j As HttpJob)
       
    If j.Success Then
         
    Log(j.GetString)
       
    End If
       j.Release
       
    'second request
       Dim j As HttpJob 'redim and initialize
       j.Initialize("", Me)
       j.Download(
    "https://www.duckduckgo.com")
       
    Wait For (j) JobDone(j As HttpJob)
       
    If j.Success Then
         
    Log(j.GetString)
       
    End If
       j.Release
    End Sub
    Now for a very common question. How to download a list of resources, one by one?
    Simple:
    Code:
    Sub Activity_Create(FirstTime As Boolean)
       DownloadMany(
    Array("http://www.google.com""http://duckduckgo.com""http://bing.com"))
    End Sub

    Sub DownloadMany (links As List)
       
    For Each link As String In links
         
    Dim j As HttpJob
         j.Initialize(
    "", Me) 'name is empty as it is no longer needed
         j.Download(link)
         
    Wait For (j) JobDone(j As HttpJob)
         
    If j.Success Then
           
    Log("Current link: " & link)
           
    Log(j.GetString)
         
    End If
         j.Release
       
    Next
    End Sub
    A sub that downloads an image and sets it to an ImageView:

    Code:
    Sub DownloadImage(Link As String, iv As ImageView)
       
    Dim j As HttpJob
       j.Initialize(
    "", Me)
       j.Download(Link)
       
    Wait For (j) JobDone(j As HttpJob)
       
    If j.Success Then
         iv.Bitmap = j.GetBitmap
       
    End If
       j.Release
    End Sub
    Example of saving the downloaded file:
    Code:
    Sub DownloadAndSaveFile (Link As String)
       
    Dim j As HttpJob
       j.Initialize(
    "", Me)
       j.Download(Link)
       
    Wait For (j) JobDone(j As HttpJob)
       
    If j.Success Then
           
    Dim out As OutputStream = File.OpenOutput(File.DirInternal, "filename.dat"False)
         
    File.Copy2(job.GetInputStream, out)
         out.Close 
    '<------ very important
       End If
       j.Release
    End Sub
    The nice thing about this sub, and all above subs as well, is that they can be called multiple times:
    Code:
    Sub Activity_Create(FirstTime As Boolean)
       
    Activity.LoadLayout("1")
       DownloadImage(
    "https://b4x-4c17.kxcdn.com/android/forum/data/avatars/m/0/1.jpg?1469350209", ImageView1)
       DownloadImage(
    "https://b4x-4c17.kxcdn.com/images3/code.png", ImageView2)
    End Sub
    The images will be downloaded concurrently.

    Tip about the code flow: Sleep and Wait For are equivalent to calling Return from the calling sub perspective.

    download.gif
     
    Last edited: Nov 9, 2018
  2. victormedranop

    victormedranop Active Member Licensed User

    Nice !!! Waiting for b4a.
     
  3. ldb68

    ldb68 Member Licensed User

    Yes me too
     
  4. Cableguy

    Cableguy Expert Licensed User

    Nice!!!!
     
  5. devmobile

    devmobile Active Member Licensed User

    Is there exist this property in current version b4a?
     
  6. klaus

    klaus Expert Licensed User

    Not yet, wait till next week.
     
    timwil likes this.
  7. JNG

    JNG Member Licensed User

    Thank This is the demand of today ......
     
  8. FrankDev

    FrankDev Active Member Licensed User

    Which is when one makes several requests but only one source does not answer.
    One has only one sub-error for all queries. So a 'job_RequestError' routine.
    Then you have to make a differentiation again from which request now the error was triggered.

    sorry Translated with google translate

    regards Frank
     
  9. Erel

    Erel Administrator Staff Member Licensed User

    There is no such thing. There is only a JobDone event. This is why you need to check that Job.Success is true.

    This is handled in the above code.
    This is the reason for the sender filter parameter (j). The correct event will reach the correct sub based on the sender filter.

    You can read about the sender filter here: https://www.b4x.com/android/forum/threads/b4x-resumable-subs-sleep-wait-for.78601/#content
     
    Last edited: May 14, 2017
    Peter Simpson likes this.
  10. FrankDev

    FrankDev Active Member Licensed User

    Hi Erel
    the way is clear. IN the Sub will be queried whether it was successful. But what if not?
    If I want to know that the request is not successful.
    the 'job_request_error' routine is raised even after a time (timeout). I see that it didn't work.
    now I would have to look with a timer if after a certain things which are.
    I would like to display data to the user.
    now waits for the query just what?
    I want to say the user... Hey... the server is not responding...
    try it later?
     
  11. Erel

    Erel Administrator Staff Member Licensed User

    JobDone will be raised and Job.Success will be false. This is also true if the server doesn't respond. The default timeout is 30 seconds. You can change it if you like: https://www.b4x.com/android/forum/pages/results/?query=httpjob+timeout

    Please start a new thread in the questions forum for further discussion.
     
    pesquera likes this.
  12. FrankDev

    FrankDev Active Member Licensed User

  13. FrankDev

    FrankDev Active Member Licensed User

    Sorry, last question.

    This works only for downloads or (auch) for HTTPPost requests ?
     
  14. Erel

    Erel Administrator Staff Member Licensed User

    This works with all requests. All that it matters is that the JobDone event is eventually raised.
     
    pesquera likes this.
  15. demasi

    demasi Active Member Licensed User

    Thank you! This is a major improvement and a long waited feature.
    Now our programs will be easier to make, read and maintain.
     
    Erel likes this.
  16. Mashiane

    Mashiane Expert Licensed User

    This can only mean I have to rewrite one of my favourate apps. This is brilliant work. Thank you very much.
     
  17. lucad

    lucad Member Licensed User

    Great! Awaiting 4b4a ;) Thank you!
     
  18. PABLO2013

    PABLO2013 Active Member Licensed User

    Regards, I have been trying to do this but I would like to know that I will be doing wrong ... thanks
    What I am trying to do is that the queries are one at a time...
    And see the results one at a time...tks

    Code:
    Sub INICIO_MouseClicked (EventData As MouseEvent)
    For i=1 To 5
        DIR(
    12)="https://www.123.com/123/"&i&"-123-"&i&"-.html"
        
    Dim job As HttpJob
        
    Wait For (job) JobDone(job As HttpJob'-------------------
        job.Initialize("123", Me)
        job.Download(DIR(
    12))
    Next
    End Sub
    Code:
    Sub JobDone(Job As HttpJob)

        
    Select Job.JobName

            
    Case "123"

                
    If Job.Success = True Then

                    
    Log(Job.Tag)
                    DIR(
    12)=Job.GetString
                       T1=Mid(DIR(
    12), DIR(12).IndexOf("<title>"),100)
                    T2=Mid(T1,
    0,T1.IndexOf("</title>")).Replace("&quot;"," PULG.").Replace("- .......","").Replace("<title>","").Replace("&amp;","&").Trim
                    
    Log(T2)
           
                
    Else
               
                    
    Log("Error:************************************************")
                    
    Log(Job.Tag)
                    
    Log("Error:************************************************")
                
    End If
                Job.Release

            
    Case "456"

                
    If Job.Success = True Then

                    
    Log(Job.Tag)
                    DIR(
    12)=Job.GetString
                       T1=Mid(DIR(
    12), DIR(12).IndexOf("<title>"),100)
                    T2=Mid(T1,
    0,T1.IndexOf("</title>")).Replace("&quot;"," PULG.").Replace("- .......","").Replace("<title>","").Replace("&amp;","&").Trim
                    
    Log(T2)

                
    Else
               
                    
    Log("Error:************************************************")
                    
    Log(Job.Tag)
                    
    Log("Error:************************************************")
           
                
    End If
           
                Job.Release

            
    End Select
    End Sub
     
    Last edited: May 17, 2017
  19. DonManfred

    DonManfred Expert Licensed User

    Code:
    Dim job As HttpJob
        job.Initialize(
    "123", Me)
        job.Download(DIR(
    12))
        
    Wait For (job) JobDone(job As HttpJob'-------------------
        If job.success then
            
    '' my code....
        end if
        job.release
    PD: It is better (ALWAYS!) to start a NEW thread for each question.
     
    Erel likes this.
  20. PABLO2013

    PABLO2013 Active Member Licensed User

    Thank you donmanfred ... sorry for understanding little ... but where place for ..... next

    What I want is to use to "WaitFor (job) JobDone(job AsHttpJob)"

    Request and scrape the information of 5 pages in an automatic but individual way

    For 1 to 5
    1. Read page server
    2. Scrape the information on the page
    3.continue with the following
    Next

    What happens to me is that it runs all the entire "for ... next" at one time and the server generates an error or block


    thank you
     
Thread Status:
Not open for further replies.
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice