Autore Topic: ListView con CustomArrayAdapter  (Letto 434 volte)

Offline AL_94

  • Nuovo arrivato
  • *
  • Post: 16
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    HTC One
  • Sistema operativo:
    Windows 8.1; Mac OS X 10.9
ListView con CustomArrayAdapter
« il: 14 Agosto 2013, 11:26:29 CEST »
0
Salve a tutti,
sono nuovo del forum quindi spero di non aver sbagliato sezione dove postare il mio problema e soprattutto spero di riuscire a descriverlo nella maniera più corretta possibile. Detto questo inizio a spiegare il mio dubbio.
Il mio programma deve gestire un database; le informazioni contenute in esso verranno messe in un Vector<?> java e poi passate al mio CustomArrayAdapter che li inserirà poi nella mia ListView. L'adapter, a quanto ho capito io, chiama il metodo getView() tante volte quanti sono gli elementi dell'Array passato; nel mio caso invece viene chiamato molte più volte invece che 8 come dovrebbe essere (gli 8 oggetti li uso come prova). Mi chiedevo quale potesse essere il problema di questo eccesso di chiamate della funzione.

P.S: sono entrato da poco nel mondo della programmazione android quindi quasi sicuramente la mia soluzione al programma sarà molto poco efficiente rispetto ad altre, quindi accetto consigli da gente più esperta su come poterlo migliorare.
Grazie

Codice del mio CustomArrayAdatpter:
Codice (Java): [Seleziona]
public class ItemListAdapter extends ArrayAdapter<ItemList> {

    Context context;
    int layoutResourceId;    
    Vector<ItemList> data;
   
    public ItemListAdapter(Context context, int layoutResourceId, Vector<ItemList> data) {
        super(context, layoutResourceId, data);
        this.context = context;
        this.layoutResourceId = layoutResourceId;
        this.data = data;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ItemListHolder holder = null;
        if(convertView == null)
        {
            LayoutInflater inflater = ((Activity)context).getLayoutInflater();
            convertView = inflater.inflate(layoutResourceId, parent, false);
            holder = new ItemListHolder();
            holder.name = (TextView)convertView.findViewById(R.id.name_LV);
            holder.type = (TextView)convertView.findViewById(R.id.type_LV);
            //holder.image = (ImageView)convertView.findViewById(R.id.image_LV);
            convertView.setTag(holder);
            Log.i("convertView == null","entrato");
        }
        else
        {
            holder = (ItemListHolder)convertView.getTag();
            Log.i("convertView != null","entrato");
        }
        ItemList item = (ItemList)data.elementAt(position);
        holder.name.setText(item.getName());
        holder.type.setText(item.getType());
        //holder.image.setImageBitmap(item.getImage(context));
        return convertView;
    }
   
    private /*o static?*/ class ItemListHolder
    {
        TextView name;
        TextView type;
        //ImageView image;
    }
   
}

LogCat:
Codice: [Seleziona]
08-14 09:18:18.066: I/convertView == null(775): entrato

08-14 09:18:18.076: I/convertView != null(775): entrato

08-14 09:18:18.086: I/convertView != null(775): entrato

08-14 09:18:18.096: I/convertView != null(775): entrato

08-14 09:18:18.119: I/convertView != null(775): entrato

08-14 09:18:18.166: I/convertView != null(775): entrato

08-14 09:18:18.207: I/convertView != null(775): entrato

08-14 09:18:18.339: W/EGL_emulation(775): eglSurfaceAttrib not implemented

08-14 09:18:18.346: I/convertView != null(775): entrato

08-14 09:18:18.396: I/convertView == null(775): entrato

08-14 09:18:18.467: I/convertView == null(775): entrato

08-14 09:18:18.526: I/convertView == null(775): entrato

08-14 09:18:18.596: I/convertView == null(775): entrato

08-14 09:18:18.676: I/convertView == null(775): entrato

08-14 09:18:18.768: I/convertView == null(775): entrato

08-14 09:18:18.787: I/Choreographer(775): Skipped 45 frames!  The application may be doing too much

work on its main thread.

08-14 09:18:18.866: I/convertView == null(775): entrato

08-14 09:18:18.876: I/convertView != null(775): entrato

08-14 09:18:18.898: I/convertView != null(775): entrato

08-14 09:18:18.906: I/convertView != null(775): entrato

08-14 09:18:18.936: I/convertView != null(775): entrato

08-14 09:18:18.946: I/convertView != null(775): entrato

08-14 09:18:18.976: I/convertView != null(775): entrato

08-14 09:18:19.206: I/convertView != null(775): entrato

08-14 09:18:19.226: I/convertView != null(775): entrato

08-14 09:18:19.256: I/convertView != null(775): entrato

08-14 09:18:19.296: I/convertView != null(775): entrato

08-14 09:18:19.443: I/convertView != null(775): entrato

08-14 09:18:19.470: I/convertView != null(775): entrato
« Ultima modifica: 14 Agosto 2013, 12:07:10 CEST da AL_94 »

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:ListView con CustomArrayAdapter
« Risposta #1 il: 14 Agosto 2013, 11:30:28 CEST »
0
Ma il problema di preciso quale è? In altre parole: questo "eccesso" di chiamate ti crea qualche malfunzionamento dell'app? Crash?


PS: di solito il LogCat si copia-e-incolla tranquillamente nel messaggio, possibilmente con il marcatore per facilitarne la lettura.
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline AL_94

  • Nuovo arrivato
  • *
  • Post: 16
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    HTC One
  • Sistema operativo:
    Windows 8.1; Mac OS X 10.9
Re:ListView con CustomArrayAdapter
« Risposta #2 il: 14 Agosto 2013, 12:02:14 CEST »
0
Al momento non crea problemi (oltre l'avviso di android che dice che forse c'è troppo lavoro in questa parte di programma), solo che in questo programma ci saranno molti più dati, e quindi non vorrei che poi l'eccesso di chiamate mi faccia crashare l'app in futuro.
Grazie per la correzione, la prossima volta metterò il LogCat direttamente nel messaggio.

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:ListView con CustomArrayAdapter
« Risposta #3 il: 14 Agosto 2013, 12:29:45 CEST »
+1
Al momento non crea problemi (oltre l'avviso di android che dice che forse c'è troppo lavoro in questa parte di programma), solo che in questo programma ci saranno molti più dati, e quindi non vorrei che poi l'eccesso di chiamate mi faccia crashare l'app in futuro.

Quella segnalazione che vedi presumo sia dovuta al fatto che stai testando su un emulatore, che storicamente è molto molto MOLTO lento (soprattutto con display grandi). Ci sono state notevolissimi avanzamenti con gli emulatori x86 e l'abilitazione dell'accelerazione grafica, ma solo per alcune versioni di API e non per tutti i pc.

In generale la tua preoccupazione è più che giusta, quel metodo viene richiamato molto spesso, ma non è tanto il numero di chiamate il problema, il fatto è che è bene fargli fare il minimo indispensabile (assegnazioni e processing minimale, come mi sembra che sia il tuo caso). Operazioni più pesanti è bene farle fuori linea in thread separati.

Se la tua lista è/sarà molto lunga/pesante, prendi in considerazione da subito l'implementazione con lazy-load (si trovano davvero tantissimi esempi in rete). E magari anche la endless list di Nicola su questo stesso forum può essere una valida scelta. [facile] Endless List, Una lista senza fine - Android Developers Italia
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline AL_94

  • Nuovo arrivato
  • *
  • Post: 16
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    HTC One
  • Sistema operativo:
    Windows 8.1; Mac OS X 10.9
Re:ListView con CustomArrayAdapter
« Risposta #4 il: 14 Agosto 2013, 14:12:10 CEST »
0
Quindi il CustomAdapter è ottimizzato bene secondo te? Cioè quando parli di
Citazione
Operazioni più pesanti è bene farle fuori linea in thread separati.
ti riferisci in generale oppure in qualche parte specifica di questa app?

Offline Sakazaki

  • Utente normale
  • ***
  • Post: 396
  • Respect: +74
    • Mostra profilo
  • Dispositivo Android:
    Sony xperia Z
  • Play Store ID:
    Saka Labs
  • Sistema operativo:
    Windows 8
Re:ListView con CustomArrayAdapter
« Risposta #5 il: 14 Agosto 2013, 14:29:16 CEST »
0
Credo che bradipao intendesse in generale.
Il meccanismo di riciclaggio delle view negli adapter è appositamente pensato per evitare il blocco che temi.
Se gli elementi della lista sono veramente tanti può convenire adottare le tecniche per liste infinite che ti ha linkato, ma solo se effettivamente è necessario.

Offline AL_94

  • Nuovo arrivato
  • *
  • Post: 16
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    HTC One
  • Sistema operativo:
    Windows 8.1; Mac OS X 10.9
Re:ListView con CustomArrayAdapter
« Risposta #6 il: 14 Agosto 2013, 14:39:36 CEST »
0
Ok grazie mille. Aspetto qualche giorno prima di taggare il post come Risolto per vedere se qualcun'altro ha avuto quel problema degli "eccessi" e sa come poterlo risolvere; più che altro per semplice curiosità.

Offline Gianluca

  • Nuovo arrivato
  • *
  • Post: 19
  • Respect: +2
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S-II (i9100)
  • Sistema operativo:
    Windows 8
Re:ListView con CustomArrayAdapter
« Risposta #7 il: 14 Agosto 2013, 21:00:15 CEST »
+1
In realtà è una questione molto semplice: per risparmiare risorse, Android non costruisce subito la lista completa. Aggiunge pezzo per pezzo solo il minimo necessario visibile a schermo. Scrollando su e giù, quindi, le singole view della lista vengono create/distrutte più di qualche volta. Questo è il motivo per cui c'è un "eccesso" di chiamate. In realtà è esattamente il contrario: c'è un'aumento di chiamate alla funzione conseguente ad un improvement della cache.
Nulla di preoccupante.

Io non so che formazione tu abbia alle spalle, ma non dovresti preoccuparti di questo genere di problemi (gestione delle risorse fino a questo livello di bassezza) sviluppando semplici app. Piuttosto è necessaria un'attenta pianificazione delle risorse delegando thread pesanti a task asincroni o servizi in backend. Questo sì è importantissimo.

Bradipao si riferiva a thread pesanti in termini generici: non fargli fetchare grandi moli di dati dal DB runtime, per capirci! Piuttosto passati il cursore nell'adapter e poi parsalo da lì, se ne hai bisogno.