Android Question Suggestions for loading images without blocking UI?

Discussion in 'Android Questions' started by FrankBerra, Jun 23, 2019.

  1. FrankBerra

    FrankBerra Active Member Licensed User

    Hello forum

    I implemented a LazyLoading with a CLV by taking inspiration here: https://www.b4x.com/android/forum/threads/b4x-xui-customlistview-lazy-loading-virtualization.87930/

    It works, but on old phones when i scroll the CLV it reads each picture at time when needed and in that moment the the Scrollview lags/bounces.

    So i tryied to use a resumable sub to load the image and then appaly it to imageview in this way:

    Code:
    Private Sub LoadPhoto
    Dim Resumable_LoadPic As ResumableSub = LoadPic(ID)
    Wait For(Resumable_LoadPic) Complete (Immagine As B4XBitmap)
    Image_view.SetBitmap(Immagine)
    End Sub

    Private LoadPic(ID As StringAs ResumableSub
       
    Dim ImmagineRoundata As B4XBitmap = CreateRoundRectBitmap(xui.LoadBitmapResize(File.DirInternalCache, ID & ".jpg"Imageview.Width, Imageview.Height, True), 7dip)

       
    Return ImmagineRoundata
    End Sub


    Sub CreateRoundRectBitmap (Input As B4XBitmap, Radius As Float) As B4XBitmap 'https://www.b4x.com/android/forum/threads/b4x-xui-rectangle-image-with-rounded-corners.86285/
       Dim BorderColor As Int = xui.Color_White
       
    Dim BorderWidth As Int = 0dip
       
    Dim c As B4XCanvas
       
    Dim xview As B4XView = xui.CreatePanel("")
       xview.SetLayoutAnimated(
    000, Input.Width, Input.Height)
       c.Initialize(xview)
       
    Dim path As B4XPath
       
    path.InitializeRoundedRect(c.TargetRect, Radius)
       c.ClipPath(
    path)
       c.DrawRect(c.TargetRect, BorderColor, 
    True, BorderWidth) 'border
       c.RemoveClip
       
    Dim r As B4XRect
       r.Initialize(BorderWidth, BorderWidth, c.TargetRect.Width - BorderWidth, c.TargetRect.Height - BorderWidth)
       
    path.InitializeRoundedRect(r, Radius - 0.7 * BorderWidth)
       c.ClipPath(
    path)
       c.DrawBitmap(Input, r)
       c.RemoveClip
       c.Invalidate
       
    Dim res As B4XBitmap = c.CreateBitmap
       c.Release
       
    Return res
    End Sub
    I was expecting (without success) to load the image from file in background without interrupting the UI avoiding in this way any lag.
    My question is: is there a better approach to (lazy)load images leaving the UI responsive?

    Thanks in advance for any suggestion!
     
  2. Brandsum

    Brandsum Active Member Licensed User

    That createroundrectbitmap is taking the time to edit all the images before loading it to view. You can use a different thread to edit your image or you can use a panel over the imageview and set the background of the panel to a white or solid color image having transparent rectangular area.
     
  3. FrankBerra

    FrankBerra Active Member Licensed User

    As you pointed out i tryed to load bitmap without "CreateRoundRectBitmap"
    Code:
    Dim ImmagineRoundata As B4XBitmap = xui.LoadBitmapResize(File.DirInternalCache, ID & ".jpg"Imageview.Width, Imageview.Height, True)
    The lag is still present, so i think i should load image in different thread.
    As i saw different libraries here on the forum to run async threads, do you have a suggestion on wich i should use?
     
  4. Erel

    Erel Administrator Staff Member Licensed User

    As the slowness happens on old phones I'm not sure that loading the images on another thread will make a big difference (it might be). It will make things much more complicated. Remember that you cannot access UI elements from a different thread.

    What happens if you load much smaller images (in XUI.LoadBitmapResize)? Does it scroll faster? If so then you can load smaller (stretched) images while the list is scrolled and only load larger images when the list stops scrolling.
     
  5. sorex

    sorex Expert Licensed User

    is this a fixed set of images that comes with the app? or does it show content of the end user?

    in the first case you could proportionally resize the images to the display size (during a splash screen?) and store them for later.
    if you load those during the lazy load it would speed up things a lot as you got rid of the oversized images overhead.
     
  6. FrankBerra

    FrankBerra Active Member Licensed User

    The images are "random" images downloaded from server and then later diplayed into the app.

    If i load images at smaller size with XUI.LoadBitmapResize it scrolls faster.

    I tryed AsyncTask library and this is my approach:

    Code:
    Private Sub LoadPhoto
       mAsyncTask.Initialize(
    "mAsyncTask")
       mAsyncTask.Execute(
    Array As Object(ID, Image_view.Width, Image_view.Height))
    End Sub

    private Sub mAsyncTask_DoInBackground(Params() As Object) As Object
       
    Dim ID As String = Params(0)
       
    Dim Larghezza As Int = Params(1)
       
    Dim Altezza As Int = Params(2
       
    Dim ImmagineRoundata As B4XBitmap = CreateRoundRectBitmap(xui.LoadBitmapResize(File.DirInternalCache, ID & ".jpg", Larghezza, Altezza, True), 7dip)
       
    Return ImmagineRoundata
    End Sub

    private Sub mAsyncTask_PostExecute(Result As Object)
       
    Dim ImmagineRoundata As B4XBitmap = Result
       Image_view.SetBitmap(ImmagineRoundata)
    End Sub
    On old phone it isn't doing miracles, it just reduces the lag a little bit.
    On more recent phones the very small and almost imperceptible lag went away, so i feel a little bit more confident now with this approach.

    I will try to optimize more by following the suggestion "load smaller (stretched) images while the list is scrolled and only load larger images when the list stops scrolling".

    Meantime thank you all for the help and suggestions!
     
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