Using DataBinding with Glide in Android

In this post on databinding, we’ll take a look at how to load images using databinding with glide in an imageview.

Let me begin by saying that you don’t need custom imageviews for this. Using binding adapter to declare a custom attribute, we can easily load a remote image into imageview with databinding.

I’ll be creating a sample project for this. It’ll have an image at the center of the screen. I’ll be loading the image from my about page.

So, let’s start!

Adding DataBinding

To include databinding in your project, go to build.gradle and add the following lines:

dataBinding {
    enabled = true
}

Also, we’ll need to include the dependency for glide library:

implementation 'com.github.bumptech.glide:glide:4.9.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'

Now, sync the project and you’re good to go. It’s as simple as that.

Creating the Layout

Now let’s create the layout. We’ll just be having an imageview at the center, with a textview below it

Here’s the activity_main.xml layout file:

<?xml version="1.0" encoding="utf-8"?>
<layout>

    <data>

        <variable
            name="user"
            type="com.example.databindingexample.User" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <TextView
            android:id="@+id/tv_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.name}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:text="This is sample text" />


        <ImageView
            android:id="@+id/imageView"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:layout_marginEnd="8dp"
            android:layout_marginBottom="8dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/tv_name" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

 

Modelling our Data

Nothing fancy. For the sake of this tutorial, we’ll just create a user object which’ll have a name and a profile image url. Here’s how it looks:

class User {
    var name: String = ""
    var profileImage: String = "https://ayusch.com/wp-content/uploads/2018/09/profile.png"
}

 

Connecting xml and Kotlin

How will the layout get it’s user variable from? For this, we’ll need to assign the object to the layout through code.

In the MainActivity.kt file, we’ll be attaching our xml and kotlin files. Here’s our MainActivity.kt file:

package com.example.databindingexample

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import androidx.databinding.DataBindingUtil
import com.example.databindingexample.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
        val user = User()
        user.name = "Ayusch"
        binding.user = user
    }
}

First, we set our contentView by using DataBindingUtils which is provided by databinding library. It needs a generic type. In our case it will be ActivityMainBinding. Don’t panic if you see all reds for that. That’s a generated file and you’ll need to build your project once to get it.

 

Using DataBinding with ImageView

Now this is where the magic happens. Here we’ll see how to load an image into our imageview using databinding with glide.

First of all, we’ll need to create a BindingAdapter which’ll have the custom logic to load our image using glide. It’s a simple method with a BindingAdapter annotation and an attribute(s)  to bind with.

Let’s see how this works. In our user class we’ll create a public static method loadImage. It’ll take two parameters. First, the view itself and second the URL of the image.

Remember: The method needs to be public static and the first parameter will be the view. This is very important.

companion object {
    @JvmStatic
    @BindingAdapter("profileImage")
    fun loadImage(view: ImageView, profileImage: String) {
        Glide.with(view.context)
            .load(profileImage)
            .into(view)
    }
}

Then, we can load the image into imageview using Glide. We’re all familiar with that.

Now to use databinding with imageview to load images, we’ll need to tell the imageview to use our custom adapter. This’ll happen in our activity_main.xml layout file. Add this line to your imageview.

app:profileImage="@{user.profileImage}"

Databinding ImageView with Placeholder

We can also accept multiple arguments in our bindingadapter. For example, one may need to load an error image, or a placeholder while our image loads.

We’ll pass a list of attributes to our bindingadapter to bind to. We’ll need to add some code to check if an error occurred and then set the error image. Here’s how it looks:

companion object {
        @JvmStatic
        @BindingAdapter(value = ["profileImage", "error"], requireAll = false)
        fun loadImage(view: ImageView, profileImage: String, error: Int) {
            Glide.with(view.context)
                .load(profileImage)
                .listener(object : RequestListener<Drawable> {
                    override fun onLoadFailed(
                        e: GlideException?,
                        model: Any?,
                        target: Target<Drawable>?,
                        isFirstResource: Boolean
                    ): Boolean {
                        view.setImageResource(error)
                        return true
                    }

                    override fun onResourceReady(
                        resource: Drawable?,
                        model: Any?,
                        target: Target<Drawable>?,
                        dataSource: DataSource?,
                        isFirstResource: Boolean
                    ): Boolean {
                        view.setImageDrawable(resource)
                        return true
                    }

                })
                .into(view)
        }
    }

Note that we’ve set requireAll to false. This ensures that this adapter is used even if one of the attributes is not set in xml. Omit this if you want to ensure this gets called only if all attributes are provided.

Now in our imageView layout, we can provide a resource for the error state.

app:error="@{user.errorImage}"

With this we end our tutorial on databinding with glide. Hope you liked it.

 

Conclusion

Databinding can be used with many other libraries just as Glide, Picasso, Fresco etc. All you need to do is alter your binding adapter’s logic.

 

*Important*: Join the AndroidVille SLACK  workspace for mobile developers where people share their learnings about everything latest in Tech, especially in Android Development, RxJava, Kotlin, Flutter, and mobile development in general.

Click on this link to join the workspace. It’s absolutely free!

Like what you read? Don’t forget to share this post on FacebookWhatsapp, and LinkedIn.

You can follow me on LinkedInQuoraTwitter, and Instagram where I answer questions related to Mobile Development, especially Android and Flutter.

If you want to stay updated with all the latest articles, subscribe to the weekly newsletter by entering your email address in the form on the top right section of this page.