1

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?

1

Architecture wise Solution 1 follows separation of concerns much better so it is actually the best if you can limit the amount of images downloaded at one time, (you shouldn't have to download all images at once). You should look into Pagination. Here is an article that might help you get started. https://www.raywenderlich.com/12244218-paging-library-for-android-with-kotlin-creating-infinite-lists

You pull a certain amount to display to the screen as they scroll you pull more. And your concern about not knowing what is displayed, that is rectified by the DiffUtil also seen in the link. The adapter knows what it has if you feed it duplicate data it will just ignore it.

NOW if you really truly can't limit the amount of images you have to download at once then Solution 3 is your next best alternative. But it is still a big problem, because say the image count is in the ten of thousands now. 10,000 url Strings is still 10,000 objects. Solution 3 will eventually fall apart.

1
  • Thanks for this link. About your objection on solution 3: the app will fall apart on repository layer in this case if there is more data than device memory. I would say that is not a problem in current scope of the question. Nov 29 at 16:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.