Glide Tutorial for Android: Getting Started

In this Glide Tutorial, you’ll learn how to use Glide to create a photo app that displays pictures to your users with different filters. By Meng Taing.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 3 of 3 of this article. Click here to view the first page.

Extending a Glide Module

Create a new class named ProgressAppGlideModule under the glide package with the following code:

@GlideModule  //1
class ProgressAppGlideModule : AppGlideModule() {

  override fun registerComponents(context: Context, glide: Glide, registry: Registry) { //2
    super.registerComponents(context, glide, registry)
    val client = OkHttpClient.Builder()
        .addNetworkInterceptor { chain -> //3
          val request = chain.request()
          val response = chain.proceed(request)
          val listener = DispatchingProgressManager()  //4
          response.newBuilder()
              .body(OkHttpProgressResponseBody(request.url(), response.body()!!, listener))  //5
              .build()
        }
        .build()
    glide.registry.replace(GlideUrl::class.java, InputStream::class.java, OkHttpUrlLoader.Factory(client)) //6
  }
}
  1. Remember the dependency you added with kapt in the build.gradle file earlier? This is where you need it.
  2. The only thing you need to do here is to override the registerComponents(...) and replace it with your own OkHttpClient.
  3. Add an Interceptor to your own OkHttpClient.
  4. This is where you create your DispatchingProgressManager instance.
  5. This is where you provide your own OkHttpProgressResponseBody with the DispatchingProgressManager instance.
  6. Glide provides a OkHttpUrlLoader.Factory class for you to conveniently replace Glide's default networking library.

Wiring Everything Together

This is the final class you've to create under the glide package. You need a class to associate the ImageView with its ProgressBar. Create a GlideImageLoader class:

class GlideImageLoader(
    private val mImageView: ImageView?,
    private val mProgressBar: ProgressBar?) { //1

  fun load(url: String?, options: RequestOptions?) { //2
    if (options == null) return

    onConnecting() //3

    DispatchingProgressManager.expect(url, object : UIonProgressListener { //4

      override val granularityPercentage: Float //5
        get() = 1.0f

      override fun onProgress(bytesRead: Long, expectedLength: Long) {
        if (mProgressBar != null) {
          mProgressBar.progress = (100 * bytesRead / expectedLength).toInt() //6
        }
      }
    })

    Glide.with(mImageView!!.context) //7
        .load(url)
        .apply(options) //8
        .listener(object : RequestListener<Drawable> { //9
          override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?,
              isFirstResource: Boolean): Boolean {
            DispatchingProgressManager.forget(url)
            onFinished()
            return false
          }

          override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?,
              dataSource: DataSource?, isFirstResource: Boolean): Boolean {

            DispatchingProgressManager.forget(url)
            onFinished()
            return false
          }
        })
        .into(mImageView)
  }


  private fun onConnecting() {
    if (mProgressBar != null) mProgressBar.visibility = View.VISIBLE
  }

  private fun onFinished() {
    if (mProgressBar != null && mImageView != null) {
      mProgressBar.visibility = View.GONE
      mImageView.visibility = View.VISIBLE
    }
  }
}

If you receive an error saying that "There are no type arguments expected for annotation class target," add the com.bumptech.glide.request.target.Target dependency at the top of your class.

Step by step:

  1. Provide ImageView and its ProgressBar to your GlideImageLoader constructor.
  2. Expose a load(url: String?, options: RequestOptions?) because you'll load the URL with Glide internally. You still accept RequestOption for transformations, placeholders, etc.
  3. When starting to load the image, make sure the ProgressBar is visible.
  4. This is where you call the expect(...) to store the progress and reference to the listener you initialize here.
  5. Set granularityPercentage with a value of 1 so that the listener will be called for every minimum one percent of the progress changed.
  6. Update the ProgressBar's progress.
  7. Call Glide to load an image here internally.
  8. Apply the options from the parameters.
  9. Glide exposes a resource listener so that you can perform extra actions if the image resource is loaded with success or failure. In either case, you want your ProgressAppGlideModule to forget the URL, hide the ProgressBar and make sure the ImageView is visible.

Up to this point, your glide package should have all the classes as shown in the screenshot below:

Applying ProgressListener to PhotoViewHolder

If you observed the layout of EditPhotoActivity closely, you might have seen a ProgressBar ready for you to manipulate.

Go back to EditPhotoActivity.kt. Right below the class declaration of EditPhotoActivity, create a private instance of GlideImageLoader as follows:

private var glideImageLoader: GlideImageLoader? = null

You can only initialize glideImageLoader inside onCreate right below setContentView(R.layout.activity_edit_photo):

glideImageLoader = GlideImageLoader(ivPhoto, progressBar)

Replace the code where you loaded the image URL with Glide before the closing bracket of applyFilters(progress: Int, photoUrl: String?) with the code below:

glideImageLoader?.load(
    photoUrl,
    RequestOptions()
        .override(500, 500)
        .transform(
            CenterCrop(),
            BlurTransformation(blurValue),
            ContrastFilterTransformation(contrastValue),
            VignetteFilterTransformation(
                PointF(0.5f, 0.5f),
                floatArrayOf(0f, 0f, 0f),
                0f,
                vignetteValue))
        .diskCacheStrategy(DiskCacheStrategy.DATA)
        .placeholder(ivPhoto.drawable))

This is similar to what you did earlier. Instead of calling Glide.with(...).load(...).into(...) directly, now you use your own glideImageLoader to do the job. You can still pass all the request options with the default Glide loader.

Run the app to check whether the ProgressBar in the EditPhotoActivity is updating as the photo is being loaded. If you don't see a ProgressBar, the photo is probably loaded from the cache. Click the Clear Cache menu item on the MainActivity screen, and then click on the photo you want to edit again:

Where to Go From Here?

You've just built your very own Instagram with Glide! You can extend the functionality of the app by allowing users to share the edited photos on social media or save to the device storage. There are many other cool things you can do with Glide such as loading GIFs and applying crossfade transitions. Keep Gliding!

Download the final project by clicking the Download Materials button at the top or bottom of this tutorial.

If you're curious about Glide's performance compared with other image loading libraries such as Picasso or Fresco, you can build a simple app that shows the downloading duration of each library. By now, you should know how to use Glide’s Request Listener and be ready to give it a try.

If you have any questions or comments, please join the forum discussion.

Meng Taing

Contributors

Meng Taing

Author

Aldo Olivares

Tech Editor

Nicole Hardina

Editor

Luke Freeman

Illustrator

Jenn Bailey

Final Pass Editor

Eric Soto

Team Lead

Over 300 content creators. Join our team.