2012-07-25 14 views
14

Ho un ListFragment supportato da un ArrayAdapter che viene popolato da un Loader. Quando l'utente fa clic su uno degli elementi, voglio passare un riferimento all'elemento selezionato, così come il resto degli elementi dell'elenco a un altro frammento. La mia domanda è come devo ottenere tutti gli articoli dall'adattatore? Qui ci sono le possibilità che vedo:Come ottenere tutti gli elementi da un ArrayAdapter

1. Mantenere un riferimento al supporto List

Creare l'adattatore in questo modo:

List<DomainObject> items = new ArrayList<DomainObject>(); 
listAdapter = new ArrayAdapter<DomainObject>(getActivity(), R.layout.mine, items); 

e poi semplicemente passare items o una copia di esso alla prossima attività.

Il lato negativo di questo è che sto facendo affidamento sul fatto non documentato che la stessa lista che passo al costruttore contiene gli articoli in seguito.

2. Scorrere l'adattatore

Quando un elemento viene cliccato, scorrere l'adattatore e costruire la lista. Sembra una quantità inutile di lavoro. Gli articoli sono contenuti in un List nell'adattatore e sto copiando manualmente ogni elemento in un nuovo elenco.

3. Mantenere una lista separata di elementi quando vengono aggiunti alla adattatore

Prima di aggiungere una voce alla scheda, aggiungere a un elenco separato che io sostengo nel frammento. Ciò è anche dispendioso in quanto l'elenco degli elementi viene copiato nello ArrayAdapter e nel frammento.

risposta

7

La soluzione che io sono andato con, nel frattempo, è semplicemente di non utilizzare ArrayAdapter. Nei casi in cui stai combattendo contro questa API, sembra che sia meglio usare solo il meno completo (e complesso) BaseAdapter. Puoi leggere di più sulla decisione di andare con BaseAdapter invece di ArrayAdapter in questo articolo: Android Adapter Good Practices.

+0

Mentre quell'articolo è per lo più buono, ignorerei la sua intera sezione sulla sicurezza del thread. Ha completamente torto sul motivo per cui vi sono supposti blocchi (a causa del filtraggio che si verifica su un thread in background) e che l''ArrayAdapter' si bloccherà già se' notifyDataSetChanged() 'viene invocato su qualsiasi argomento tranne il thread dell'interfaccia utente. –

+0

@ scompt.com Penso che il link che hai postato sia sbagliato per spiegare ArrayAdapter. Sembra spiegare solo ArrayAdapter . Sono un po 'confuso ... – theMfromA

+0

Dalla pagina che hai collegato ... "Può solo visualizzare testo." => Sbagliato. "Ti costringe a fornire un elenco di oggetti CharSequence ..." => Sbagliato "Richiede che tu fornisca una risorsa di layout che contenga solo un TextView" => Sbagliato. Tutte le ipotesi sono errate ... Non intendo che ArrayAdapter sia migliore di BaseAdapter, ma le basi sono sbagliate. – Loenix

-2

Penso che il primo metodo sia il modo migliore per farlo.

Non penso, i dati sarebbero originali per l'altra attività. perché, dovresti passare gli articoli tramite bundle, quindi l'oggetto è scritto prima su bundle e poi nella prossima attività che leggiamo da bundle.

Tuttavia, se si utilizza un altro modo per passare l'elenco, utilizzare list.clone() per creare un nuovo oggetto, anziché passare quello originale.

27

Sono un po 'in ritardo rispetto al gioco, ma mi sono imbattuto in un problema simile.

Un modo per occuparsi di # 1 sarebbe mantenere il riferimento all'elenco all'interno di una sottoclasse di ArrayAdapter, in modo che il riutilizzo sia controllato dall'oggetto adattatore.

Qualcosa di simile:

public class DomainAdapter extends ArrayAdapter<DomainObject> { 

    private final List<DomainObject> items; 

    public DomainAdapter(Context context, List<DomainObject> items) { 
     super(context, R.layout.mine, items); 
     this.items = items; 
    } 

    public List<DomainObject> getItems() { 
     return items; 
    } 
} 
+9

Nota. Se si prevede di filtrare l'adattatore a un certo punto, questo metodo ha il potenziale per fallire. L'esecuzione di un filtro, all'interno di ArrayAdapter, creerà una nuova istanza dell'elenco. Il che significa che gli "elementi" definiti esternamente non saranno più la stessa lista. Il che significa che non sarà sincronizzato se le modifiche verranno apportate successivamente. Puoi leggere maggiori informazioni qui: http://www.jaysoyer.com/2014/07/constructor-woes-androids-arrayadapter/ –

0

Un test rapido indica che il metodo 1 funziona.Sembra il più veloce e più pulito, ma dal momento che non è documentato, è possibile testarlo su tutte le piattaforme previste e ogni volta che si aggiornano nel caso in cui la struttura sottostante di ArrayAdapter cambi.

Sto usando compilare SDK versione 22 e min SDK versione 10.

0

Il metodo migliore è quello di "mantenere un riferimento alla lista", ma non di passaggio "oggetti" variabile/parametro al costruttore:

List<DomainObject> items = new ArrayList<DomainObject>(); listAdapter = new ArrayAdapter<DomainObject>(getActivity(), R.layout.mine);

In questo modo si crea un'istanza di ArrayList solo come un array vuoto e si dovrà gestire l'elenco da soli.

Problemi correlati