0Pricing
Android Academy · Lezione

Caricare immagini con Coil

Caricamento asincrono delle immagini in Compose

Caricare immagini con Coil è una lezione Android Academy gratuita su CoddyKit. Questa è la lezione 1 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Android Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Android Academy include 4 lezioni in totale.

Perché serve un image loader

La maggior parte delle app moderne mostra immagini provenienti da Internet: foto profilo, immagini di prodotti e miniature di articoli. Scaricare e decodificare correttamente queste immagini è più difficile di quanto sembri.

È necessario recuperare i byte dalla rete in un thread in background, decodificarli in una bitmap, memorizzarli nella cache per non scaricarli di nuovo e annullare la richiesta se l'utente scorre oltre. Farlo manualmente è soggetto a errori.

Coil (Coroutine Image Loader) gestisce tutto questo al posto vostro con una piccola API compatibile con Compose. In questa lezione caricherete la vostra prima immagine remota.

Aggiungere Coil al progetto

Coil viene distribuito come dipendenza Gradle. Per Jetpack Compose serve l'artefatto coil-compose, che fornisce il composable AsyncImage.

Aggiungetelo al file build.gradle.kts del modulo. Coil 3 è la versione principale corrente e funziona su più piattaforme; qui useremo l'integrazione con Compose.

// build.gradle.kts (module level)
dependencies {
    implementation("io.coil-kt.coil3:coil-compose:3.0.4")
    implementation("io.coil-kt.coil3:coil-network-okhttp:3.0.4")
}

Autorizzazione Internet

Per scaricare immagini da un URL, la vostra app necessita dell'autorizzazione INTERNET. È una normale autorizzazione concessa al momento dell'installazione, quindi dovete solo dichiararla nel manifest. Non viene mostrata alcuna richiesta durante l'esecuzione.

Senza di essa, ogni richiesta di rete fallisce con un'eccezione di sicurezza.

<!-- AndroidManifest.xml -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-permission android:name="android.permission.INTERNET" />
    <application ...>
        ...
    </application>
</manifest>

Il vostro primo AsyncImage

Il modo più semplice per mostrare un'immagine remota in Compose è AsyncImage. Fornite un model, di solito una stringa URL, e un contentDescription; Coil farà il resto: recupero in background, decodifica e visualizzazione.

Usa automaticamente coroutine legate alla composizione, quindi la richiesta viene annullata se il composable lascia lo schermo.

import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import coil3.compose.AsyncImage

@Composable
fun Avatar() {
    AsyncImage(
        model = "https://example.com/avatar.png",
        contentDescription = "User avatar",
        modifier = Modifier.size(96.dp)
    )
}

contentScale: come si adatta l'immagine

Le immagini raramente corrispondono esattamente alle dimensioni dello spazio disponibile nel layout. ContentScale controlla come viene ridimensionata la bitmap all'interno dei suoi limiti.

  • ContentScale.Crop riempie il riquadro e ritaglia ciò che fuoriesce, ottimo per avatar e miniature.
  • ContentScale.Fit mantiene visibile l'intera immagine, lasciando eventualmente dello spazio vuoto.
  • ContentScale.FillBounds allunga l'immagine per riempire il riquadro, rischiando di deformarla.

Crop è la scelta più comune per gli spazi di dimensioni fisse.

import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.unit.dp
import coil3.compose.AsyncImage

@Composable
fun CircleAvatar(url: String) {
    AsyncImage(
        model = url,
        contentDescription = "Avatar",
        contentScale = ContentScale.Crop,
        modifier = Modifier
            .size(80.dp)
            .clip(CircleShape)
    )
}

Creare una richiesta con ImageRequest

Passare una stringa URL è la soluzione più rapida. Per avere un controllo maggiore, create un ImageRequest. Potrete impostare opzioni come crossfade, intestazioni, trasformazioni e chiavi della cache.

Serve un Context, che Compose fornisce tramite LocalContext.current.

import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
import coil3.compose.AsyncImage
import coil3.request.ImageRequest
import coil3.request.crossfade

@Composable
fun ProductImage(url: String) {
    val context = LocalContext.current
    val request = ImageRequest.Builder(context)
        .data(url)
        .crossfade(true)
        .build()

    AsyncImage(
        model = request,
        contentDescription = "Product photo"
    )
}

Crossfade per caricamenti fluidi

Per impostazione predefinita, un'immagine compare istantaneamente al termine del caricamento, il che può risultare brusco. crossfade(true) fa comparire gradualmente l'immagine con una breve animazione.

Potete anche indicare una durata in millisecondi per ottenere una dissolvenza più lenta o più rapida. Questo piccolo accorgimento rende gli elenchi molto più curati.

import coil3.request.ImageRequest
import coil3.request.crossfade
import android.content.Context

fun smoothRequest(context: Context, url: String) =
    ImageRequest.Builder(context)
        .data(url)
        .crossfade(durationMillis = 300)
        .build()

Caricare da fonti diverse

Il model di AsyncImage è flessibile. Coil può caricare molti tipi di origine, non solo URL remoti:

  • Una String o una Uri per file di rete o locali.
  • L'ID di una risorsa drawable (R.drawable.logo).
  • Un File presente sul dispositivo.
  • Una Uri di contenuto proveniente dal selettore di foto.

Lo stesso composable può quindi gestire senza problemi immagini remote e locali.

import android.net.Uri
import androidx.compose.runtime.Composable
import coil3.compose.AsyncImage

@Composable
fun FlexibleImage(source: Any) {
    // source can be a URL String, a Uri, a File, or a resource id
    AsyncImage(
        model = source,
        contentDescription = null
    )
}

// Examples:
// FlexibleImage("https://example.com/pic.jpg")
// FlexibleImage(Uri.parse("content://media/external/images/1"))

Reagire allo stato di caricamento

A volte è necessario sapere se l'immagine è in caricamento, è stata caricata correttamente o ha restituito un errore, così da mostrare un'interfaccia diversa. AsyncImagePainter espone questo stato, ma l'approccio più semplice è SubcomposeAsyncImage, che consente di fornire contenuti specifici per ogni stato.

Approfondiremo i placeholder nella prossima lezione; qui vediamo la struttura di un caricamento consapevole dello stato.

import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.runtime.Composable
import coil3.compose.SubcomposeAsyncImage

@Composable
fun StatefulImage(url: String) {
    SubcomposeAsyncImage(
        model = url,
        contentDescription = "Photo",
        loading = { CircularProgressIndicator() }
    )
}

L'annullamento è automatico

Uno dei principali vantaggi di Coil è l'annullamento automatico. Poiché AsyncImage avvia la richiesta all'interno della composizione, quando il composable lascia lo schermo, per esempio quando una riga scorre fuori da una LazyColumn, la richiesta in corso viene annullata.

Questo consente di risparmiare banda e CPU e impedisce di eseguire lavoro inutile. Non dovete scrivere alcun codice per l'annullamento: è per questo che Coil funziona così bene negli elenchi lunghi.

import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import coil3.compose.AsyncImage

@Composable
fun PhotoFeed(urls: List<String>) {
    LazyColumn {
        items(urls) { url ->
            AsyncImage(
                model = url,
                contentDescription = null,
                modifier = Modifier
                    .fillMaxWidth()
                    .height(200.dp)
            )
        }
    }
}

Una scheda immagine completa

Combiniamo ciò che abbiamo imparato: una scheda con un'immagine remota che riempie la parte superiore, usa il crossfade e viene ritagliata a un'altezza fissa. È il modello fondamentale che riutilizzerete continuamente.

import androidx.compose.foundation.layout.*
import androidx.compose.material3.Card
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import coil3.compose.AsyncImage
import coil3.request.ImageRequest
import coil3.request.crossfade

@Composable
fun ImageCard(title: String, imageUrl: String) {
    val context = LocalContext.current
    Card(modifier = Modifier.fillMaxWidth().padding(16.dp)) {
        Column {
            AsyncImage(
                model = ImageRequest.Builder(context)
                    .data(imageUrl)
                    .crossfade(true)
                    .build(),
                contentDescription = title,
                contentScale = ContentScale.Crop,
                modifier = Modifier.fillMaxWidth().height(180.dp)
            )
            Text(text = title, modifier = Modifier.padding(16.dp))
        }
    }
}

Verifica rapida

Quale composable di coil-compose è il modo più semplice per visualizzare tramite URL un'immagine remota in Jetpack Compose?

Riepilogo

Avete caricato le vostre prime immagini remote con Coil. Concetti chiave:

  • Aggiungete coil-compose e una dipendenza di rete OkHttp, oltre all'autorizzazione INTERNET.
  • AsyncImage(model = url, contentDescription = ...) è la soluzione più rapida.
  • Usate ContentScale.Crop con dimensioni fisse per avatar e miniature.
  • Create un ImageRequest per il crossfade e un controllo maggiore.
  • Coil annulla automaticamente le richieste in corso quando i composable lasciano lo schermo.

Prossimo argomento: rendere elegante il caricamento con placeholder e stati di errore.

Domande Frequenti

La lezione «Caricare immagini con Coil» è gratuita?

Sì — il testo completo di «Caricare immagini con Coil» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Android Academy, passa a CoddyKit PRO. Il corso Android Academy include 4 lezioni in totale.

Cosa imparerò in «Caricare immagini con Coil»?

Caricamento asincrono delle immagini in Compose Eserciti Android Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Android Academy?

Non è richiesta alcuna esperienza precedente. Android Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 1 di 4.

Quanto tempo richiede la lezione «Caricare immagini con Coil»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Android Academy?

Sì. Ogni lezione Android Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Caricare immagini con Coil
  2. Placeholder e stati di errore
  3. Caching e prestazioni
  4. Riprodurre audio e video
← Torna a Android Academy