Glide e Picasso in Android Java: Caricamento Immagini da URL

A clean, modern illustration showing Android app development with image loading. A smartphone displaying photos loaded from URLs, with Glide and Picasso library logos, Java code snippets in the background. Dark blue and green color scheme, tech style.

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.

Glide e Picasso Android Java caricamento immagini da URL

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 Context passato (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):

CaratteristicaGlidePicasso
Performance generaleMolto alta, ottimizzata per scroll e listeBuona, ma in genere leggermente sotto Glide in scenari intensivi
Supporto GIF / animazioniOttimo, supporto GIF animati nativoLimitato
Trasformazioni avanzateMolto ricco e estendibileSemplice, meno estensibile
Dimensione libreriaPiù grandePiù leggera
Gestione lifecycleIntegrata (Activity, Fragment, ecc.)Più manuale, meno integrata
APIFluente, ma talvolta più complessaMolto semplice e leggibile
Configurabilità cacheMolto configurabileConfigurazione 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.

Commenti

Rispondi

Scopri di più da App Tutorial

Abbonati ora per continuare a leggere e avere accesso all'archivio completo.

Continua a leggere