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:
- Initialization: It retrieves references to UI elements (button, progress bar, text view, and image view) and defines the image URL.
- 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. - Image Request: The
ImageRequest
object is then added to the request queue managed by theVolleySingleton
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:
- Singleton Instance: It ensures only one instance of the class exists and provides a method to access it.
- Request Queue: It initializes a request queue using the application context to prevent memory leaks.
- Image Loader (Optional): It creates an
ImageLoader
instance for efficient image caching using an LRU cache. - 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.
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)
}
}
}
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)
}
}
<?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>
// Volley network library
implementation 'com.android.volley:volley:1.2.1'
- android kotlin - Volley JsonArrayRequest
- android kotlin - Volley JsonObjectRequest
- android kotlin - Volley string request
- android kotlin - Chip center text
- android kotlin - EditText allow only numbers
- android kotlin - EditText allow only characters
- android kotlin - EditText allow only characters and numbers
- android kotlin - EditText numbers only programmatically
- android kotlin - EditText min length
- android kotlin - EditText limit number range
- android kotlin - EditText input filter decimal
- android kotlin - EditText set max length programmatically
- android kotlin - EditText rounded corners programmatically
- android kotlin - EditText border color programmatically
- android kotlin - EditText remove underline while typing