Caricare immagini da URL in Android Java con Glide e Picasso
Glide e Picasso in Android Java rendono evidente come gestire il caricamento di immagini da URL in un’app Android nativa sia un problema solo apparentemente banale. Se fatto nel modo sbagliato (es. usando AsyncTask o thread manuali e gestendo da soli il caching), si rischiano blocchi dell’interfaccia (UI thread bloccato), consumo eccessivo di memoria (Out Of Memory, OOM) e prestazioni scarse, soprattutto in liste come RecyclerView. In questa guida completa vedremo come risolvere il problema in modo pulito e robusto usando due librerie consolidate: Glide e Picasso, entrambe in Java.

Introduzione al problema: thread, cache e Out Of Memory
Caricare immagini da Internet significa eseguire richieste HTTP, decodificare i dati binari in oggetti Bitmap e mostrarli in una ImageView. Se gestisci tutto manualmente, devi occuparti di:
- Eseguire il download fuori dal main thread (altrimenti l’app si blocca e Android genera
NetworkOnMainThreadException). - Ridimensionare (downsampling) le immagini per evitare consumi di memoria inutili e OOM.
- Gestire una cache in memoria e su disco per evitare di riscaricare sempre le stesse immagini.
- Gestire il recycling delle view in liste come
RecyclerView, evitando che le immagini “saltino” tra le righe.
Librerie come Glide e Picasso nascono proprio per astrarre tutta questa complessità: tu fornisci una URL e una ImageView, la libreria gestisce thread, cache, ridimensionamento, placeholder, retry, ecc.
Glide in Android Java: caratteristiche principali
Glide è una libreria di caricamento immagini sviluppata da BumpTech e sponsorizzata da Google in diversi progetti. È pensata per essere veloce, efficiente in memoria e molto configurabile, con supporto avanzato per GIF, video e trasformazioni.
Dipendenza Gradle per Glide in Android Java
Nel tuo file app/build.gradle (o nel blocco dependencies del modulo), aggiungi:
dependencies {
implementation 'com.github.bumptech.glide:glide:4.16.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.16.0'
}
Assicurati di usare una versione aggiornata al momento in cui stai sviluppando (controlla sempre la pagina GitHub ufficiale di Glide).
Uso base di Glide in Android Java
L’utilizzo base di Glide è estremamente semplice: passi un Context, una URL e una ImageView.
String imageUrl = "https://example.com/immagine.jpg";
ImageView imageView = findViewById(R.id.imageView);
Glide.with(this)
.load(imageUrl)
.into(imageView);
Questo codice:
- Esegue il download su thread in background.
- Applica automaticamente il caching in memoria e su disco.
- Gestisce il ciclo di vita in base al
Contextpassato (Activity, Fragment, ecc.).
Placeholder, error e fallback con Glide
I placeholder sono immagini mostrate mentre il download è in corso o quando si verifica un errore. Devi prima definire le risorse in res/drawable (ad esempio placeholder.png, error.png).
Glide.with(this)
.load(imageUrl)
.placeholder(R.drawable.placeholder)
.error(R.drawable.error)
.fallback(R.drawable.placeholder) // Se l'URL è null
.into(imageView);
Resize e trasformazioni con Glide
Per ridimensionare l’immagine o cambiare la strategia di adattamento:
int width = 300; // px
int height = 200; // px
Glide.with(this)
.load(imageUrl)
.override(width, height) // richiede valori in pixel
.centerCrop() // taglia l'immagine mantenendo l'aspect ratio
// .fitCenter() // alternativa: scala per contenere senza tagliare
.into(imageView);
In un’app reale, usa valori in dp convertiti in px tramite getResources().getDisplayMetrics().density oppure lascia che sia Glide a gestire automaticamente le dimensioni, impostando il layout dell’ImageView via XML (es. match_parent e adjustViewBounds).
Uso di Glide in RecyclerView
Glide è pensato per funzionare molto bene con RecyclerView, evitando problemi di immagini che cambiano mentre scorri la lista. Vediamo un adattatore base.
public class GlideImageAdapter extends RecyclerView.Adapter<GlideImageAdapter.ImageViewHolder> {
private List<String> imageUrls;
private Context context;
public GlideImageAdapter(Context context, List<String> imageUrls) {
this.context = context;
this.imageUrls = imageUrls;
}
@NonNull
@Override
public ImageViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_image, parent, false);
return new ImageViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ImageViewHolder holder, int position) {
String url = imageUrls.get(position);
Glide.with(context)
.load(url)
.placeholder(R.drawable.placeholder)
.error(R.drawable.error)
.centerCrop()
.into(holder.imageView);
}
@Override
public int getItemCount() {
return imageUrls != null ? imageUrls.size() : 0;
}
static class ImageViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
ImageViewHolder(@NonNull View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.imageView);
}
}
}
Il layout item_image.xml può essere ad esempio:
<?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"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="200dp"
android:scaleType="centerCrop"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Picasso in Android Java: caratteristiche principali
Picasso, sviluppata da Square, è una libreria più minimalista ma ancora molto utilizzata. Offre un’API semplice e leggibile, ideale per progetti che non richiedono funzionalità avanzate come il supporto GIF complesso o trasformazioni molto spinte.
Dipendenza Gradle per Picasso in Android Java
Aggiungi la dipendenza nel build.gradle del modulo:
dependencies {
implementation 'com.squareup.picasso:picasso:2.8'
}
Uso base di Picasso in Android Java
L’uso base di Picasso è molto lineare:
String imageUrl = "https://example.com/immagine.jpg";
ImageView imageView = findViewById(R.id.imageView);
Picasso.get()
.load(imageUrl)
.into(imageView);
Picasso si occupa di tutto ciò che riguarda threading, caching e gestione della coda di richieste.
Placeholder ed error con Picasso
Come in Glide, puoi impostare immagini mostrate durante il caricamento o in caso di errore:
Picasso.get()
.load(imageUrl)
.placeholder(R.drawable.placeholder)
.error(R.drawable.error)
.into(imageView);
Resize con Picasso
Per ridimensionare l’immagine, Picasso espone i metodi resize() e centerCrop()/centerInside():
Picasso.get()
.load(imageUrl)
.resize(300, 200) // px
.centerCrop() // taglia mantenendo l'aspect ratio
// .centerInside() // alternativa: tutto dentro senza tagli
.into(imageView);
Uso di Picasso in RecyclerView
L’integrazione in un RecyclerView.Adapter è analoga a Glide:
public class PicassoImageAdapter extends RecyclerView.Adapter<PicassoImageAdapter.ImageViewHolder> {
private List<String> imageUrls;
public PicassoImageAdapter(List<String> imageUrls) {
this.imageUrls = imageUrls;
}
@NonNull
@Override
public ImageViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_image, parent, false);
return new ImageViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ImageViewHolder holder, int position) {
String url = imageUrls.get(position);
Picasso.get()
.load(url)
.placeholder(R.drawable.placeholder)
.error(R.drawable.error)
.fit() // adatta alle dimensioni dell'ImageView
.centerCrop()
.into(holder.imageView);
}
@Override
public int getItemCount() {
return imageUrls != null ? imageUrls.size() : 0;
}
static class ImageViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
TextView textTitle;
ImageViewHolder(@NonNull View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.imageView);
textTitle = itemView.findViewById(R.id.textTitle);
}
}
}
Glide vs Picasso in Android Java: tabella comparativa
Entrambe le librerie sono mature e affidabili. La scelta spesso si basa sullo stile API preferito e sui requisiti specifici del progetto. La tabella seguente riassume le differenze principali (situazione indicativa, può variare con le versioni):
| Caratteristica | Glide | Picasso |
|---|---|---|
| Performance generale | Molto alta, ottimizzata per scroll e liste | Buona, ma in genere leggermente sotto Glide in scenari intensivi |
| Supporto GIF / animazioni | Ottimo, supporto GIF animati nativo | Limitato |
| Trasformazioni avanzate | Molto ricco e estendibile | Semplice, meno estensibile |
| Dimensione libreria | Più grande | Più leggera |
| Gestione lifecycle | Integrata (Activity, Fragment, ecc.) | Più manuale, meno integrata |
| API | Fluente, ma talvolta più complessa | Molto semplice e leggibile |
| Configurabilità cache | Molto configurabile | Configurazione base |
In pratica, se hai una lista complessa, molte immagini, GIF o trasformazioni particolari, Glide tende a essere la scelta preferibile. Se invece vuoi una soluzione minimale e leggibile, Picasso è più che sufficiente.
Esempio pratico completo con RecyclerView (Glide + Picasso alternabili)
Vediamo ora un esempio completo di schermata che mostra una RecyclerView con immagini da URL. Mostreremo un adattatore che può usare Glide o Picasso, in base a una semplice configurazione.
Layout dell’Activity con Glide e Picasso
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Layout dell’item per Android Java
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="8dp">
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="200dp"
android:scaleType="centerCrop" />
<TextView
android:id="@+id/textTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="16sp"
android:paddingTop="4dp"
android:textColor="@android:color/black" />
</LinearLayout>
Model e Activity con Glide e Picasso in Android Java
public class ImageItem {
private String url;
private String title;
public ImageItem(String url, String title) {
this.url = url;
this.title = title;
}
public String getUrl() {
return url;
}
public String getTitle() {
return title;
}
}
public class ImageListActivity extends AppCompatActivity {
private RecyclerView recyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image_list);
recyclerView = findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
List<ImageItem> items = createDummyData();
boolean useGlide = true; // cambia a false per usare Picasso
ImageListAdapter adapter = new ImageListAdapter(this, items, useGlide);
recyclerView.setAdapter(adapter);
}
private List<ImageItem> createDummyData() {
List<ImageItem> list = new ArrayList<>();
list.add(new ImageItem("https://picsum.photos/600/400?image=10", "Immagine 1"));
list.add(new ImageItem("https://picsum.photos/600/400?image=20", "Immagine 2"));
list.add(new ImageItem("https://picsum.photos/600/400?image=30", "Immagine 3"));
list.add(new ImageItem("https://picsum.photos/600/400?image=40", "Immagine 4"));
list.add(new ImageItem("https://picsum.photos/600/400?image=50", "Immagine 5"));
return list;
}
}
Adapter che supporta sia Glide che Picasso
public class ImageListAdapter extends RecyclerView.Adapter<ImageListAdapter.ViewHolder> {
private List<ImageItem> items;
private Context context;
private boolean useGlide;
public ImageListAdapter(Context context, List<ImageItem> items, boolean useGlide) {
this.context = context;
this.items = items;
this.useGlide = useGlide;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_image, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
ImageItem item = items.get(position);
holder.textTitle.setText(item.getTitle());
if (useGlide) {
Glide.with(context)
.load(item.getUrl())
.placeholder(R.drawable.placeholder)
.error(R.drawable.error)
.centerCrop()
.into(holder.imageView);
} else {
Picasso.get()
.load(item.getUrl())
.placeholder(R.drawable.placeholder)
.error(R.drawable.error)
.fit()
.centerCrop()
.into(holder.imageView);
}
}
@Override
public int getItemCount() {
return items != null ? items.size() : 0;
}
static class ViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
TextView textTitle;
ViewHolder(@NonNull View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.imageView);
textTitle = itemView.findViewById(R.id.textTitle);
}
}
}
Questo esempio mostra chiaramente quanto poco codice sia necessario per ottenere una lista performante di immagini remote, indipendentemente dalla libreria scelta.
Errori comuni e come evitarli
1. Caricare immagini sul main thread
Non usare mai HttpURLConnection o librerie di rete in modo diretto sul main thread per scaricare e decodificare immagini. Glide e Picasso lo fanno già in background. Evita quindi di avere logiche aggiuntive di download prima di passare a Glide/Picasso: passa direttamente l’URL.
2. Non riutilizzare correttamente RecyclerView
Non impostare manualmente setImageDrawable(null) o setImageBitmap(null) in onBindViewHolder() se stai usando Glide/Picasso: entrambi gestiscono già la coda di richieste e la cancellazione quando le view vengono riciclate. Se devi liberare risorse, fallo a livello di Activity/Fragment usando i metodi offerti (ad esempio Glide.with(fragment).onStop() viene automatico se passi il Fragment).
3. Ignorare il ridimensionamento
Caricare immagini nella loro risoluzione originale (ad esempio foto da 4000×3000 px) in una ImageView da 200dp è uno spreco enorme di memoria e banda. Usa sempre centerCrop()/fitCenter() e, se necessario, override() (Glide) o resize()/fit() (Picasso) per adeguare le dimensioni.
4. Non gestire placeholder ed error
Se non imposti placeholder o immagini di errore, l’utente può vedere flash, glitch o riquadri vuoti quando scorri velocemente. È buona pratica avere almeno un placeholder neutro e una piccola icona di errore.
5. Confondere context e scope
Per Glide, passare il Context corretto è importante per la gestione del ciclo di vita:
Glide.with(this)dentro un’Activity.Glide.with(fragment)dentro un Fragment.Glide.with(view)se hai solo una View (Glide risale al Context associato).
In Picasso questo aspetto è meno critico ma è comunque preferibile evitare di legare caricamenti a context che vivono troppo a lungo (per evitare leak).
Conclusione
Caricare immagini da URL in Android Java usando Glide e Picasso non è solo questione di “scaricare e mostrare”: serve rispettare il main thread, ottimizzare memoria e banda, gestire cache e riciclo delle view. Librerie come Glide e Picasso astraggono questa complessità permettendoti di scrivere poche righe di codice per ottenere risultati professionali.
Glide è ideale per applicazioni grafiche intense, con molte immagini, GIF e trasformazioni avanzate, grazie a performance e flessibilità superiori. Picasso è perfetto per chi cerca un’API pulita e minimale, con tutte le funzionalità essenziali già pronte.
Partendo dagli esempi di questa guida puoi integrare rapidamente il caricamento di immagini remote nella tua app, sia in schermate singole che in liste complesse con RecyclerView, riducendo il rischio di errori comuni come OOM e blocchi dell’interfaccia.
Per approfondire, consulta la documentazione ufficiale di Glide e Picasso su GitHub.

Rispondi