Scenario:
A very simple android app needed to be developed. It has just one screen with a list of items. Each item has a label and an icon. We fetch the item list from the server, and the server response contains labels and URLs of icons. ViewModel
asks Repository
for the list, the View
observers the list reference in ViewModel
to update the UI whenever there is a change. The view uses an Adapter
to populate the data into ListView
. The adapter is aware of the items are on the screen so it can render only those, plus a few more which are going to appear next.
Problem: Where in that whole scenario should the images be downloaded from URLs?
Solution 1 (bad): We fetch the images in ViewModel
and pass the image data
along with labels. View
and Adapter
won't have to know about the image fetching mechanism, but we will need to download all images even if there are 1000. Because ViewModel
is not aware of which items are on the screen. Implementation in adapter would be something like this:
currentView.iconHolder.image = list[position].iconImageData
Solution 2 (somewhat bad): Instead of adding the image data
to the model, ViewModel
adds a reference to ImageLoader
to the Model
objects resulting in something like LoadableImage
. The adapter can use that reference to trigger image loading for the items it decides.
list[position].loadableImage.getBitmap { bitmap ->
currentView.iconHolder.image = bitmap
}
The drawback is, we have an unrelated reference in the model classes.
Solution 3 (Ok):
We pass/inject ImageLoader
to Adapter
itself. We use it to fetch the images from URLs.
imageLoader.getBitmap(list[position].iconUrl, onBitmapDownloaded: { bitmap ->
currentView.iconHolder.image = bitmap
})
The only problem is, the view needs to know about ImageLoader
.
Is there a better solution than Solution 3?