Android Question Suggestions for loading images without blocking UI?

FrankBerra

Active Member
Licensed User
Longtime 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:

B4X:
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 String) As 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(0, 0, 0, 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!
 

Brandsum

Well-Known 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.
 
Upvote 0

FrankBerra

Active Member
Licensed User
Longtime User
As you pointed out i tryed to load bitmap without "CreateRoundRectBitmap"
B4X:
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?
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime 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.
 
Upvote 0

sorex

Expert
Licensed User
Longtime 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.
 
Upvote 0

FrankBerra

Active Member
Licensed User
Longtime 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:

B4X:
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!
 
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…