android kotlin - Volley image request

Android Kotlin - Volley Image Request: Downloading and Displaying Images

This code demonstrates fetching and displaying an image from a remote URL using Volley, a popular networking library for Android. The code is written in Kotlin and utilizes separate classes for the main activity (MainActivity.kt) and a singleton class for managing the Volley request queue (VolleySingleton.kt).

The application showcases a simple user interface with a button, a progress bar, a text view, and an image view. Clicking the button triggers the image download process.

Breakdown of the Code

The MainActivity.kt class handles the user interaction and manages the Volley request. Here's a breakdown of its functionalities:

  1. Initialization: It retrieves references to UI elements (button, progress bar, text view, and image view) and defines the image URL.
  2. Button Click Listener: Clicking the button disables itself, shows the progress bar, and creates an ImageRequest object. This object specifies the URL, response and error listeners, image scaling options, and decoding configuration.
  3. Image Request: The ImageRequest object is then added to the request queue managed by the VolleySingleton class.

The VolleySingleton.kt class implements the singleton pattern to provide a single instance of the Volley request queue throughout the application. Here's what it offers:

  1. Singleton Instance: It ensures only one instance of the class exists and provides a method to access it.
  2. Request Queue: It initializes a request queue using the application context to prevent memory leaks.
  3. Image Loader (Optional): It creates an ImageLoader instance for efficient image caching using an LRU cache.
  4. Adding Requests: It provides a method to add any type of Volley request (not just image requests) to the request queue.

Finally, the activity_main.xml file defines the layout of the user interface with the button, progress bar, text view, and image view.


MainActivity.kt

package com.cfsuman.kotlintutorials

import android.app.Activity
import android.graphics.Bitmap
import android.os.Bundle
import android.view.View
import android.widget.*
import com.android.volley.toolbox.ImageRequest


class MainActivity : Activity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // get the widgets reference from XML layout
        val button = findViewById<Button>(R.id.button)
        val progressBar = findViewById<ProgressBar>(R.id.progressBar)
        val textView = findViewById<TextView>(R.id.textView)
        val imageView = findViewById<ImageView>(R.id.imageView)

        // url to fetch/download image
        val imageUrl = "https://images.pexels.com/photos/1085551/" +
                "pexels-photo-1085551.jpeg?" +
                "auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260"


        // fetch image from url using volley network library
        button.setOnClickListener {
            // disable the button itself
            it.isEnabled = false

            progressBar.visibility = View.VISIBLE

            // request a image response from the provided url
            val imageRequest = ImageRequest(
                imageUrl,
                {bitmap -> // response listener
                    textView.text = "Image downloaded successfully!"
                    imageView.setImageBitmap(bitmap)
                    progressBar.visibility = View.INVISIBLE
                },
                0, // max width
                0, // max height
                ImageView.ScaleType.CENTER_CROP, // image scale type
                Bitmap.Config.ARGB_8888, // decode config
                {error-> // error listener
                    textView.text = error.message
                    progressBar.visibility = View.INVISIBLE
                    it.isEnabled = true
                }
            )

            VolleySingleton.getInstance(applicationContext)
                .addToRequestQueue(imageRequest)
        }
    }
}
VolleySingleton.kt

package com.cfsuman.kotlintutorials

import android.content.Context
import android.graphics.Bitmap
import android.util.LruCache
import com.android.volley.Request
import com.android.volley.RequestQueue
import com.android.volley.toolbox.ImageLoader
import com.android.volley.toolbox.Volley


class VolleySingleton constructor(context: Context) {
    companion object {
        @Volatile
        private var INSTANCE: VolleySingleton? = null
        fun getInstance(context: Context) =
            INSTANCE ?: synchronized(this) {
                INSTANCE ?: VolleySingleton(context).also {
                    INSTANCE = it
                }
            }
    }
    val imageLoader: ImageLoader by lazy {
        ImageLoader(requestQueue,
            object : ImageLoader.ImageCache {
                private val cache = LruCache<String, Bitmap>(20)
                override fun getBitmap(url: String): Bitmap {
                    return cache.get(url)
                }
                override fun putBitmap(url: String, bitmap: Bitmap) {
                    cache.put(url, bitmap)
                }
            })
    }
    private val requestQueue: RequestQueue by lazy {
        // applicationContext is key, it keeps you from leaking the
        // Activity or BroadcastReceiver if someone passes one in.
        Volley.newRequestQueue(context.applicationContext)
    }
    fun <T> addToRequestQueue(req: Request<T>) {
        requestQueue.add(req)
    }
}
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<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"
    android:background="#DCDCDC"
    android:padding="24dp">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Run Volley"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:visibility="invisible"
        app:layout_constraintBottom_toBottomOf="@+id/button"
        app:layout_constraintStart_toEndOf="@+id/button"
        app:layout_constraintTop_toTopOf="@+id/button" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:fontFamily="sans-serif"
        android:textSize="24sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button"
        tools:text="TextView" />

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="0dp"
        android:layout_height="300dp"
        android:layout_marginTop="16dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView" />

</androidx.constraintlayout.widget.ConstraintLayout>
gradle dependencies

// Volley network library
implementation 'com.android.volley:volley:1.2.1'
More android kotlin tutorials