Displaying images in an Android application: delegates, tests and no pain

Displaying images in an Android application: delegates, tests and no pain

Revolut app

Our application has many types of pictures to display – there are lists of transactions with different icons, lists of cards, Lottie animations, gifs. I’ll show you how we work with pictures using the example of a list of transactions.

Our list of transactions has several dozen types of cells. For example, we’ll take five:

Different types of transactions where we show the picture

In each case, the picture is taken from a separate source or generated.
How the standard way of displaying pictures works

Let’s create an adapter for such a list.

class TransactionsAdapter: RecyclerView.Adapter () {
private var items = mutableListOf ()

override fun onCreateViewHolder (parent: ViewGroup, viewType: Int): ViewHolder {
    val view = LayoutInflater.from (parent.context)
        .inflate (R.layout.view_transaction, parent, false)
    return ViewHolder (view)
}

override fun onBindViewHolder (holder: ViewHandler, position: Int) = Unit

override fun getItemCount () = items.size

class ViewHolder (itemView: View): RecyclerView.ViewHolder (itemView) {
    private val imageView: ImageView = itemView.findViewById (R.id.image)
}

}

This is what the standard adapter template for RecyclerView would look like. Let’s implement value binding:

override fun onBindViewHolder (holder: ViewHandler, position: Int) {
val transaction = items [position]
when {
transaction.isContactWithAvatar () -> {
// Load and display the avatar
}
! transaction.isContactWithAvatar () -> {
// Display avatar
}
transaction.isMerchantWithAvatar () -> {
// Load and display the avatar
}
! transaction.isMerchantWithAvatar () -> {
// Load image from source
}
}
}

A footcloth of conditions appears, because inside the adapter we build separate logic for each type of transaction. You can complicate and use your ViewType for each source. Moreover, the adapter contract pushes for this:

override fun getItemViewType (position: Int): Int {
val transaction = items [position]
return when {
transaction.isContactWithAvatar () -> VIEW_TYPE_CONTACT_WITH_AVATAR
! transaction.isContactWithAvatar () -> VIEW_TYPE_CONTACT_WITHOUT_AVATAR
transaction.isMerchantWithAvatar () -> VIEW_TYPE_MERCHANT_WITH_AVATAR
! transaction.isMerchantWithAvatar () -> VIEW_TYPE_MERCHANT_WITHOUT_AVATAR
else -> VIEW_TYPE_UNKNOWN
}
}

Considering that in our case there can be several dozen types of transactions, the standard way of implementing the adapter is not suitable.
How to improve the adapter

We can distinguish two main approaches to extension – ViewType or delegates. The rest are not specifically mentioned: in essence, they will be similar to the second approach.

The first option – ViewType – can be used when the application is simple, that is, it contains one simple list and, for example, a couple of screens. This method is not suitable for us, because such adapters cannot be reused. If we expand the adapter by adding new ViewType, the adapter will grow uncontrollably. In addition, we will have to create our own adapters for each screen.

You may also like

Building successful mobile apps: UX, product thinking, and reliable engineering

Building successful mobile apps: UX, product thinking, and reliable engineering

Mobile applications live in a brutally competitive environment. People install them in seconds and uninstall them just as quickly when...

Designing a secure, high-retention mobile entertainment experience: lessons for modern app builders

Designing a secure, high-retention mobile entertainment experience: lessons for modern app builders

Mobile entertainment apps—games, streaming platforms, interactive communities—are among the hardest products to build well. They must be fast, visually smooth,...

Why UX Design Determines the Success of Mobile Applications

Why UX Design Determines the Success of Mobile Applications

People download mobile applications within seconds and uninstall them, if not instantly, then soon enough. What drives people to a...

What Modern Customers Expect from Digital Products

What Modern Customers Expect from Digital Products

People interact with digital products from morning to night: banking, shopping, learning, working, and relaxing all flow through screens. Because...

Back to Top