Autore Topic: ListView con immagine prese da web  (Letto 547 volte)

Offline emaborsa

  • Utente normale
  • ***
  • Post: 274
  • Java Developer
  • Respect: +33
    • Google+
    • emaborsa
    • Mostra profilo
    • www.emaborsa.com
  • Dispositivo Android:
    Samsung Galaxy S2
  • Sistema operativo:
    Linux 10 - Win8.1 - Android 4.1.2
ListView con immagine prese da web
« il: 03 Marzo 2014, 23:17:18 CET »
0
Ciao,
devo implementare una lista, dove l'icona di ogni riga viene presa da un URL sul WEB.
Il codice per farlo pensavo di usare questo:

Codice (Java): [Seleziona]
InputStream is;
    try {
        is = (InputStream) new URL("url_to_image").getContent();
        textView.setCompoundDrawables(Drawable.createFromStream(is, "src name"), null, null, null);
    } catch (MalformedURLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

Il problema è che non posso farlo durante il popolamento della riga/lista stessa, dato che android non permette di fare operazioni "pesanti" nel thread principale. L'idea era quella di farlo andare in un AsynkTasc Prima della creazione della lista, questo però comporta un ritardo enorme al caricamento iniziale.

Qualche idea?

Offline ciccio

  • Utente junior
  • **
  • Post: 65
  • Respect: +7
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Francesco Cervone
  • Sistema operativo:
    Mac OS X 10.9
Re:ListView con immagine prese da web
« Risposta #1 il: 04 Marzo 2014, 08:40:29 CET »
0
Purtroppo mi sono imbattuto anche io in questo problema. Ci sono varie soluzioni:
  • La più utilizzata è sicuramente questa. Se ci fai caso anche twitter e tante altre app usano questo metodo. Si mette un background grigio chiaro (o come vuoi) nell'imageview e durante il popolamento della riga fai un AsyncTask che va a prendere l'immagine. Ovviamente usa una sorta di cache per fare questa cosa altrimenti faresti una richiesta ogni volta che diventa visibile la riga.
  • Come hai detto tu, carichi tutto prima ed alla fine componi la lista. Se la lista è grossa lo sconsiglio perché c'è un inutile spreco di memoria e tempo di esecuzione.
« Ultima modifica: 04 Marzo 2014, 13:15:13 CET da ciccio, Reason: Non è la soluzione ottimale. Picasso lo è. »

Offline emaborsa

  • Utente normale
  • ***
  • Post: 274
  • Java Developer
  • Respect: +33
    • Google+
    • emaborsa
    • Mostra profilo
    • www.emaborsa.com
  • Dispositivo Android:
    Samsung Galaxy S2
  • Sistema operativo:
    Linux 10 - Win8.1 - Android 4.1.2
Re:ListView con immagine prese da web
« Risposta #2 il: 04 Marzo 2014, 08:51:00 CET »
0
Si difatti al momento ho fatto come il punto 1. Devo gestire una lista di categorie di circa 15 elementi, per caricare queste ci mette circa 2-3 secondi. Se invece carico tutti i sottoelementi delle categorie arriviamo ad oltre 5 secondi. Ho pensato anche io ad una sorta di cache, ma non so ancora bene come fare. Cosa mi consigli?

Ho l'incarico di sviluppare questa applicazione da un tipo, il quale già ha la versione per iPhone. La cosa che mi turba è che su iPhone non noto nessuna latenza per il caricamento di queste immagini e questa cosa non mi da pace, non sapendo come abbiano fatto....a meno che iPhone non gestisca in maniera ottimizzata queste cose. Che dici?
« Ultima modifica: 04 Marzo 2014, 08:52:32 CET da emaborsa »

Offline ciccio

  • Utente junior
  • **
  • Post: 65
  • Respect: +7
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Francesco Cervone
  • Sistema operativo:
    Mac OS X 10.9
Re:ListView con immagine prese da web
« Risposta #3 il: 04 Marzo 2014, 09:03:56 CET »
0
La cache la puoi gestire in vari modi.
  • Puoi gestirla tramite oggetti, per esempio crei un array che associa l'immagine (il bitmap) alla riga. Se hai 15 righe, crei un array da 15 elementi ed ogni volta che ti serve l'immagine, se la corrispondente posizione è null allora la vai a prendere dal server, altrimenti ti prendi il bitmap.
  • L'altra soluzione è di gestire il tutto tramite database. Ogni volta che prendi un immagine la salvi nel db. Ti può essere utile anche nelle connessioni successive se le immagini sono statiche e non cambiano. Quando ti serve la selezioni dal db e la piazzi nella lista.

Anche iPhone non può fare richieste a server in modo sincrono (se non erro), quindi se puoi chiedi come hanno risolto questo problema. Quando si sviluppa un'applicazione per iOS ed Android è giusto che i due team parlino e si confrontino tra di loro.
« Ultima modifica: 04 Marzo 2014, 13:15:23 CET da ciccio, Reason: Non è la soluzione ottimale. Picasso lo è. »

Offline emaborsa

  • Utente normale
  • ***
  • Post: 274
  • Java Developer
  • Respect: +33
    • Google+
    • emaborsa
    • Mostra profilo
    • www.emaborsa.com
  • Dispositivo Android:
    Samsung Galaxy S2
  • Sistema operativo:
    Linux 10 - Win8.1 - Android 4.1.2
Re:ListView con immagine prese da web
« Risposta #4 il: 04 Marzo 2014, 09:07:46 CET »
0
Avevo pensato a varie soluzioni anche io.
- Caricarle dinamicamente e salvarle direttamente sul telefono così le ho sempre li se necessarie in un futuro.
- Crearmi una struttura dati che mi faccia da cache.

Poi ho trovato QUESTO....l'hai mai sentito e/o usato?

Offline Nicola_D

  • Moderatore
  • Utente storico
  • *****
  • Post: 2479
  • SBAGLIATO!
  • Respect: +323
    • Github
    • Google+
    • nicoladorigatti
    • Mostra profilo
  • Dispositivo Android:
    Nexus 6p, Nexus 4, Nexus S, Nexus 7(2012)
  • Sistema operativo:
    Windows 7
Re:ListView con immagine prese da web
« Risposta #5 il: 04 Marzo 2014, 09:18:45 CET »
0
prova ad usare picasso!
IMPORTANTE:NON RISPONDO A PROBLEMI VIA MESSAGGIO PRIVATO
LOGCAT: Non sai cos'è? -> Android Debug Bridge | Android Developers
               Dov'è in Eclipse? -> Window -> Open Prospective -> DDMS e guarda in basso!
[Obbligatorio] Logcat, questo sconosciuto! (Gruppo AndDev.it LOGTFO) - Android Developers Italia

Offline ciccio

  • Utente junior
  • **
  • Post: 65
  • Respect: +7
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Francesco Cervone
  • Sistema operativo:
    Mac OS X 10.9
Re:ListView con immagine prese da web
« Risposta #6 il: 04 Marzo 2014, 09:20:46 CET »
0
Avevo pensato a varie soluzioni anche io.
- Caricarle dinamicamente e salvarle direttamente sul telefono così le ho sempre li se necessarie in un futuro.
- Crearmi una struttura dati che mi faccia da cache.
E' esattamente quello che ti ho consigliato :)

Poi ho trovato QUESTO....l'hai mai sentito e/o usato?
No mai usato e mai sentito.

Offline Ricky`

  • Amministratore
  • Utente storico
  • *****
  • Post: 3487
  • Respect: +506
    • Github
    • Google+
    • rciovati
    • Mostra profilo
Re:ListView con immagine prese da web
« Risposta #7 il: 04 Marzo 2014, 10:01:35 CET »
0
prova ad usare picasso!

Mi unisco al suggerimento di usare Picasso.

Non ha senso perdere tempo a costruirsi cose che librerie fanno già in modo egregio.

Offline GabMarioPower

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 606
  • Respect: +152
    • Github
    • Google+
    • gabrielemariotti
    • GabMarioPower
    • Mostra profilo
  • Play Store ID:
    GAB+MARIO+DEV
  • Sistema operativo:
    Ubuntu 14.04 , Win 10
Re:ListView con immagine prese da web
« Risposta #8 il: 04 Marzo 2014, 10:44:54 CET »
0
prova ad usare picasso!

Mi unisco al suggerimento di usare Picasso.

Non ha senso perdere tempo a costruirsi cose che librerie fanno già in modo egregio.


Una delle migliori regole è NON REINVENTARE LA RUOTA.
Quello che tu cerchi di fare è qualcosa di ampiamente usato.
Usa Picasso, Ion, Android-Universal-Image-Loader o Volley.
Sono tutte librerie che eseguono il download in modo asincrono , utilizzando un meccanismo di cache a vari livelli (Ram, e disco) ampiamente utilizzate e soprattutto con supporto.
Personalmente consiglio Picasso per la sua semplicità di utilizzo.



La cache la puoi gestire in vari modi.
  • Puoi gestirla tramite oggetti, per esempio crei un array che associa l'immagine (il bitmap) alla riga. Se hai 15 righe, crei un array da 15 elementi ed ogni volta che ti serve l'immagine, se la corrispondente posizione è null allora la vai a prendere dal server, altrimenti ti prendi il bitmap.

Ma anche no.
Questa soluzione ha dei difetti.
Il primo è che la devi popolare prima, il che significa andare a dover eseguire dei download o controlli quando non ha senso (perchè chi lo dice che visualizzerai tutte e 15 le immagini?).
Se la lista diventa di 50, la cosa diventa seria. Scarichi 50 immagini?

Poi ti espone a problemi di memory leak o memory crash o gestioni complesse. Mentre esegui 15 download , il tuo utente esce dalla lista. Che fai dei 15 download?
Il tuo utente rientra nella lista, li ricarichi tutti un'altra volta? Dove lo memorizzi questo array?

La soluzione più semplice è caricare l'immagine nel getView() del tuo adapter.
Il getView viene chiamato proprio quando c'è bisogno di visualizzare quel item.
Qui chiami in modo asincrono il downlaod dell'immagine (un async task, ma picasso e compagnia lo fanno in automatico cachando il valore).

Quello che chiami "background grigio chiaro", è un placeholder, ampiamente supportato da queste librerie.


Offline ciccio

  • Utente junior
  • **
  • Post: 65
  • Respect: +7
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Francesco Cervone
  • Sistema operativo:
    Mac OS X 10.9
Re:ListView con immagine prese da web
« Risposta #9 il: 04 Marzo 2014, 10:54:12 CET »
0

Questa soluzione ha dei difetti.
Il primo è che la devi popolare prima, il che significa andare a dover eseguire dei download o controlli quando non ha senso (perchè chi lo dice che visualizzerai tutte e 15 le immagini?).
Se la lista diventa di 50, la cosa diventa seria. Scarichi 50 immagini?

Poi ti espone a problemi di memory leak o memory crash o gestioni complesse. Mentre esegui 15 download , il tuo utente esce dalla lista. Che fai dei 15 download?
Il tuo utente rientra nella lista, li ricarichi tutti un'altra volta? Dove lo memorizzi questo array?
Forse non è stato chiaro il mio messaggio, ma ho scritto chiaramente che non deve essere popolato prima, ma a richiesta, soltanto se serve l'immagine. Per il resto sono perfettamente d'accordo.

Offline emaborsa

  • Utente normale
  • ***
  • Post: 274
  • Java Developer
  • Respect: +33
    • Google+
    • emaborsa
    • Mostra profilo
    • www.emaborsa.com
  • Dispositivo Android:
    Samsung Galaxy S2
  • Sistema operativo:
    Linux 10 - Win8.1 - Android 4.1.2
Re:ListView con immagine prese da web
« Risposta #10 il: 04 Marzo 2014, 13:31:09 CET »
0
OK,
grazie a tutti i per i post. Ho usato Picasso e devo dire che fantastico. Una linea di codice e fa tutto. Ammetto però che il caricamento è lento...non capisco come facciano su iphone ad essere così rapidi.

Offline Nicola_D

  • Moderatore
  • Utente storico
  • *****
  • Post: 2479
  • SBAGLIATO!
  • Respect: +323
    • Github
    • Google+
    • nicoladorigatti
    • Mostra profilo
  • Dispositivo Android:
    Nexus 6p, Nexus 4, Nexus S, Nexus 7(2012)
  • Sistema operativo:
    Windows 7
Re:ListView con immagine prese da web
« Risposta #11 il: 04 Marzo 2014, 14:09:51 CET »
0
puoi usare okhttp per avere un miglior controllo e probabile maggior rapidità, con picasso si può usare:
vedi questo esempio
https://github.com/swankjesse/android-http-examples/blob/master/picasso-app/src/com/publicobject/pictures/PicturesApp.java
IMPORTANTE:NON RISPONDO A PROBLEMI VIA MESSAGGIO PRIVATO
LOGCAT: Non sai cos'è? -> Android Debug Bridge | Android Developers
               Dov'è in Eclipse? -> Window -> Open Prospective -> DDMS e guarda in basso!
[Obbligatorio] Logcat, questo sconosciuto! (Gruppo AndDev.it LOGTFO) - Android Developers Italia

Offline Ricky`

  • Amministratore
  • Utente storico
  • *****
  • Post: 3487
  • Respect: +506
    • Github
    • Google+
    • rciovati
    • Mostra profilo
Re:ListView con immagine prese da web
« Risposta #12 il: 04 Marzo 2014, 14:11:31 CET »
0
puoi usare okhttp per avere un miglior controllo e probabile maggior rapidità, con picasso si può usare:
vedi questo esempio
https://github.com/swankjesse/android-http-examples/blob/master/picasso-app/src/com/publicobject/pictures/PicturesApp.java

Non credo che influenzi così tanto.

Offline Nicola_D

  • Moderatore
  • Utente storico
  • *****
  • Post: 2479
  • SBAGLIATO!
  • Respect: +323
    • Github
    • Google+
    • nicoladorigatti
    • Mostra profilo
  • Dispositivo Android:
    Nexus 6p, Nexus 4, Nexus S, Nexus 7(2012)
  • Sistema operativo:
    Windows 7
Re:ListView con immagine prese da web
« Risposta #13 il: 04 Marzo 2014, 14:20:23 CET »
0
Non credo che influenzi così tanto.
boh, dipende, io avevo provato su un'app desktop (quindi java pura) e la differenza si sentiva parecchio. Non era download di immagini ma rest service, il mio codice non gestiva gzip ne altro, non ho indagato molto ma avevo risposte anche nell'ordine di 1/3 del tempo.
Vista la semplicità con cui si può integrare okHttp, tentare non nuoce
IMPORTANTE:NON RISPONDO A PROBLEMI VIA MESSAGGIO PRIVATO
LOGCAT: Non sai cos'è? -> Android Debug Bridge | Android Developers
               Dov'è in Eclipse? -> Window -> Open Prospective -> DDMS e guarda in basso!
[Obbligatorio] Logcat, questo sconosciuto! (Gruppo AndDev.it LOGTFO) - Android Developers Italia

Offline emaborsa

  • Utente normale
  • ***
  • Post: 274
  • Java Developer
  • Respect: +33
    • Google+
    • emaborsa
    • Mostra profilo
    • www.emaborsa.com
  • Dispositivo Android:
    Samsung Galaxy S2
  • Sistema operativo:
    Linux 10 - Win8.1 - Android 4.1.2
Re:ListView con immagine prese da web
« Risposta #14 il: 05 Marzo 2014, 18:02:07 CET »
0
Per curiosità ho provato ad implementare la versione con OkHttp...e devo dire che è più lenta. Forse perchè dalla versione 1.0.2 alla versione 2.1.1 l'hanno migliorata. Difatti nella 1.0.2 non c'è più la classe OkHttp e nemmeno il metodo loader nel Builder.