Impossibile utilizzare LayoutInflater in adattatore personalizzato
-
29-09-2019 - |
Domanda
non vedo a scrivere un adattatore personalizzato per popolare un ListView con 3 textviews per riga. Ho trovato un po 'di codice di esempio per fare questo, ma quello che sembrava il migliore era al: http://www.anddev.org/custom_widget_adapters-t1796.html
Dopo un paio di modifiche minori per correggere alcuni problemi di compilazione con la più recente di Android SDK, mi ci sono in esecuzione, solo per ottenere l'eccezione:
ERRORE / AndroidRuntime (281): java.lang.UnsupportedOperationException: addView (View, LayoutParams) non è supportato in AdapterView
Così ho fatto un sacco di ricerca e un sacco di trovate possibili ragioni e correzioni per questo. Nessuno dei quali ha cambiato una cosa. Il mio codice adattatore è attualmente:
public class WeatherAdapter extends BaseAdapter {
private Context context;
private List<Weather> weatherList;
public WeatherAdapter(Context context, int rowResID,
List<Weather> weatherList ) {
this.context = context;
this.weatherList = weatherList;
}
public int getCount() {
return weatherList.size();
}
public Object getItem(int position) {
return weatherList.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
Weather weather = weatherList.get(position);
//LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LayoutInflater inflater = LayoutInflater.from(context);
View v = inflater.inflate(R.layout.weather_row, null, true);
TextView cityControl = (TextView)v.findViewById( R.id.city );
TextView temperatureControl = (TextView)v.findViewById( R.id.temperature );
ImageView skyControl = (ImageView)v.findViewById( R.id.sky );
return v;
}
}
Così ho cercato il modo commentata di ottenere il gonfiatore, e attualmente senza commenti fuori. Ho cercato di passaggio "padre" per gonfiare così come nullo, e passando "vero", "falso" e omettendo completamente l'ultimo parametro. Nessuno di loro hanno lavorato, e tutti gli esempi che ho trovato finora sono stati a partire dal 2008, che ho la sensazione è un po 'obsolete.
Se qualcuno potrebbe aiutare con questo, allora mi piacerebbe risolvere il problema.
Soluzione
Sono un principiante anche in modo da prendere questa risposta con un pizzico di sale - se non lo fa lavorare, andare avanti e Google ancora un po '. Non hanno familiarità con AdapterView
dal momento che tradizionalmente ho un ListView
o GridView
e un costume adattatore esteso fuori una BaseAdapter
e poi listView.setAdapter(myCustomAdapter)
.
Si potrebbe provare a fare qualcosa di simile all'interno della classe WeatherAdapter
:
public void addToList(Weather mWeather) {
weatherList.add(mWeather);
}
Poi, nella classe che le chiamate WeatherAdapter
:
weatherAdapter.addToList(weatherToAdd);
weatherAdapter.notifyDataSetChanged();
Inoltre è necessario ottimizzare più nel metodo GetView:
Altri suggerimenti
Credo che questa linea è in errore:
View v = inflater.inflate(R.layout.weather_row, null, true);
È necessario invece:
View v = inflater.inflate(R.layout.weather_row, parent, false);
Il falso rende la vista gonfiato indipendente del genitore, non collegato ad esso, che sembra molto strano per essere il design accettato per visualizzazioni personalizzate all'interno AdapterView
s. Perché questo è così, trovo assolutamente sconcertante, ma il modello di cui sopra ha lavorato per me.
Per il metodo AdaptertView addView
:
addView void (Bambini)
Questo metodo non è supportato e getta un UnsupportedOperationException quando chiamato."(dalla documentazione Android)
Probabilmente la procedura di gonfiaggio chiama il metodo addView
e questo non è possibile da un AdapterView
, o la sua AdapterView
.
Dalla documentazione:
"oggetto Un adattatore funge da ponte tra un AdapterView e dati sottostanti per tale vista. Il Adattatore consente l'accesso ai dati elementi. L'adattatore è anche responsabile per fare un View per ciascun elemento della set di dati".
Credo che l'operazione di gonfiaggio potrebbe essere fatto da una semplice attività che modelli la vista e tutte le altre operazioni, ad esempio, il recupero dei dati e mostrando i dati in altre classi.
La speranza che sarà utile!
@ risposta di Axel22 è fondamentale, ma ci sono un paio di altre cose mancanti dal codice. In primo luogo, si dovrebbe essere estendendo sia BaseAdapter o ArrayAdapter, a seconda delle preferenze. In secondo luogo, si vuole ottenere nella pratica di utilizzare un ViewHolder per evitare di fare chiamate eccessivi per findViewById, e (soprattutto) riciclare la vostra vista.
private Class ViewHolder {
public TextView cityControl;
public TextView temperatureControl;
public ImageView skyControl;
public ViewHolder(TextView cityControl, TextView temperatureControl, ImageView skyControl) {
this.cityControl = cityControl;
this.temperatureControl = temperatureControl;
this.skyControl = skyControl;
}
La vostra funzione GetView può riciclare vista e utilizzare la classe ViewHolder
come segue:
public View getView(int position, View convertView, ViewGroup parent) {
Weather weather = weatherList.get(position);
// This is how you attempt to recycle the convertView, so you aren't
// needlessly inflating layouts.
View v = convertView;
ViewHolder holder;
if (null == v) {
v = LayoutInflater.from(getContext()).inflate(R.layout.weather_row, parent, false);
TextView cityControl = (TextView)v.findViewById( R.id.city );
TextView temperatureControl = (TextView)v.findViewById( R.id.temperature );
ImageView skyControl = (ImageView)v.findViewById( R.id.sky );
holder = new ViewHolder(cityControl, temperatureControl, skyControl);
v.setTag(holder);
} else {
holder = (ViewHolder) v.getTag();
}
holder.cityControl.setText("Metropolis");
holder.temperatureControl.setText("78");
holder.skyControl.setImageResource(R.drawable.daily_planet);
return v;
}
Per tonnellate di più esempi (e altri suggerimenti per l'ottimizzazione), vedi questo post del blog (o semplicemente google per ViewHolder).