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 = "http://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 Facebook, Whatsapp, and LinkedIn.
You can follow me on LinkedIn, Quora, Twitter, 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.