Async Image Loading #5140
-
Hi, I'm writing a chat app client which loads a large amount of images in a dynamic fashion from the internet (I do not know the file locations during compile time). Currently I see no easy way to load these images without blocking the main thread for a while. Currently I have a Message component that represents a message, and the messages are retrieved via the worker thread, and displayed via a closure in I tried following this, but this gets really confusing as this hangs/stalls the worker thread until all the images are downloaded and accounted for. Ideally, I would prefer to display the messages first and then load the images dynamically. Then I tried storing a Now what I could do is spawn many more threads, each downloading a single image, then looping through the message model to find the right one, and then modifying the appropriate component, but this would involve some messy code and is not a preferable solution., while also blocking the main thread while searching for the right message. Essentially, what I'd like to do is modify a component in a for loop after it has been created while not blocking the main thread as much as possible, is there any clean/idiomatic way to do this? Alternatively if there is a way to load images from the internet asynchronously, that would work too. Thanks. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments
-
I think you have the choice between having a thread that can use upgrade_in_event_loop for each Message and you can user set_row_data on the paricular row to set the image when loaded. Alternative is a similar pattern, but using async rust (slint::spawn_locale) |
Beta Was this translation helpful? Give feedback.
-
I recently spent a lot of time getting lazy image loading working well in my app. Here is roughly how I do it. Here is an example of my "artist list" page, which is a grid view with thousands of images. I added a few comments to note the image handling:
And here is the lazy_get function that is called above:
So, the way this all works is that when we go to the artist list page, we nearly instantly get the view of thousands of cards, and they will either have placeholder or cached images. Each request to create a card adds a request to the image loader, which goes into a thread pool. When the request is executed on the thread pool it loads the image (the slow part), resizes it (also slow), and then calls the set closure that was specified in the initial call to lazy_get. Since these set clousures update the model in place, rather than resetting the model, we get a stable view where the images pop in as they are loaded. The result is that the UI stays snappy and the images load in as quick as I can. One thing to note: In Debug mode this will still be a little clunky. There is a slowdown that I think is within Slint when setting the image on the model that I have not been able to track down. But, in Release mode this is completely negligible and the result is extremely fast. Even in Debug mode it's usable - the scroll view just skips a little while the images are still loading. Hope this helps. It was a real struggle to get it performant and I'm very happy with the final result. Jason |
Beta Was this translation helpful? Give feedback.
I recently spent a lot of time getting lazy image loading working well in my app. Here is roughly how I do it.
Here is an example of my "artist list" page, which is a grid view with thousands of images. I added a few comments to note the image handling: