Android: EfficientAdapter avec deux points de Vue différents

Je suis en utilisant une version étendue de BaseAdapter basé sur la EfficientAdapter exemple dans le kit de développement de démonstration des échantillons.

Mes données est essentiellement un objet (ListPlaces) qui détient une ArrayList avec la liste actuelle des lieux, accessible via listPlaces.getValues(). Cette liste de tableaux, les données sont triées par gamme et la ArrayList se composent de quelques éléments spéciaux (séparateurs), l'absence de données, mais un separator indicateur a la valeur true.

Maintenant, chaque fois que mon EfficientAdapter devient un objet de données qui est un séparateur, il retourne false pour public boolean isEnabled(int position) et public View getView(int position, View convertView, ViewGroup parent) gonfle deux configurations différentes en fonction de si les données actuelles de l'objet se compose de données réelles ou c'est juste un séparateur de mannequin.

Cela fonctionne très bien, si je me gonfler à la disposition de tous les temps. Toutefois, en gonflant la disposition de tous les temps et de l'appel de findViewById rend le ListView presque unusabely lent.

J'ai donc essayé d'utiliser le EfficientAdapter avec ViewHolder approche. Mais cela ne fonctionne pas, tout droit sorti de la boîte, parce que les deux points de vue différents d'une tentative d'accès. Donc, chaque fois que mon convertView != null (l'autre cas), accède à des éléments sur la mise en page par l'intermédiaire de notre ViewHolder et lorsque la précédente a été un séparateur d'elle bien sûr, ne veut pas travailler pour accéder à un TextView qui est disponible uniquement sur le "vrai" éléments de mise en page.

Moi aussi je force mon getView() pour gonfler la disposition non seulement lorsque convertView == null, mais aussi lors de la précédente listRow est différent de celui en cours: if (convertView == null || (listRow != listRow_previous)) { [....] }

Cela semble presque travailler maintenant. Ou, au moins, il ne plante pas dès le début. Mais il se bloque toujours et je ne sais pas ce que j'ai à faire différents. J'ai essayé de regarder dans convertView.getID() et convertView.getResources(), mais ce n'était pas vraiment utile à ce jour. Peut-être quelqu'un d'autre a une idée de comment je peux vérifier si mon convertView correspond à l'élément de la liste mise en page ou le séparateur de liste de mise en page. Merci.

Voici le code. Où jamais il y a une [...] j'ai pris d'autres moins importants, code pour le rendre plus facile à lire et à comprendre:

private class EfficientAdapter extends BaseAdapter {
private LayoutInflater mInflater;
private ListPlaces listPlaces;
private ListRow listRow;
private ListRow listRow_previous;
public EfficientAdapter(Context context, ListPlaces listPlaces) {
//Cache the LayoutInflate to avoid asking for a new one each time.
mInflater = LayoutInflater.from(context);
//Data
this.listPlaces = listPlaces;
}
/**
* The number of items in the list is determined by the number of items
* in our ArrayList
*
* @see android.widget.ListAdapter#getCount()
*/
public int getCount() {
return listPlaces.getValues().size();
}
/**
* Since the data comes from an array, just returning the index is
* sufficent to get at the data. If we were using a more complex data
* structure, we would return whatever object represents one row in the
* list.
*
* @see android.widget.ListAdapter#getItem(int)
*/
public Object getItem(int position) {
return position;
}
/**
* Use the array index as a unique id.
*
* @see android.widget.ListAdapter#getItemId(int)
*/
public long getItemId(int position) {
return position;
}
@Override
public  boolean isEnabled(int position) {
//return false if item is a separator:
if(listPlaces.getValues().get(position).separator >= 0)
return false;
else
return true;
}
@Override
public boolean  areAllItemsEnabled() {
return false;         
}
/**
* Make a view to hold each row.
*
* @see android.widget.ListAdapter#getView(int, android.view.View,
*      android.view.ViewGroup)
*/
public View getView(int position, View convertView, ViewGroup parent) {
//Get the values for the current list element
ListPlacesValues curValues = listPlaces.getValues().get(position);
if (curValues.separator >= 0) 
listRow = ListRow.SEPARATOR;
else
listRow = ListRow.ITEM;
Log.i(TAG,"Adapter: getView("+position+") " + listRow + " (" + listRow_previous + ") -> START");
//A ViewHolder keeps references to children views to avoid unneccessary calls
//to findViewById() on each row.
ViewHolder holder;
//When convertView is not null, we can reuse it directly, there is no need
//to reinflate it. We only inflate a new View when the convertView supplied
//by ListView is null.
if (convertView == null || (listRow != listRow_previous)) {
Log.i(TAG, "--> (convertView == null) at position: " + position);
//Creates a ViewHolder and store references to the two children views
//we want to bind data to.
holder = new ViewHolder();
if (listRow == ListRow.SEPARATOR) {
convertView = mInflater.inflate(R.layout.taxonomy_list_separator, null);
holder.separatorText = (TextView) convertView.findViewById(R.id.separatorText);
convertView.setTag(holder);
Log.i(TAG,"\tCREATE SEPARATOR: convertView ID: " + convertView.getId() + " Resource: " + convertView.getResources());
}
else {
convertView = mInflater.inflate(R.layout.taxonomy_listitem, null);
holder.name = (TextView) convertView.findViewById(R.id.name);
holder.category = (TextView) convertView.findViewById(R.id.category);
//[...]
convertView.setTag(holder);
Log.i(TAG,"\tCREATE ITEM: convertView ID: " + convertView.getId() + " Resource: " + convertView.getResources());
}
} else {
//Get the ViewHolder back to get fast access to the TextView
//and the ImageView.
Log.i(TAG,"\tconvertView ID: " + convertView.getId() + " Resource: " + convertView.getResources());
holder = (ViewHolder) convertView.getTag();
convertView.setAnimation(null);
}
/* Bind the data efficiently with the holder */
if (listRow == ListRow.SEPARATOR) {
String separatorText;
switch (curValues.separator) {
case 0: separatorText="case 0"; break;
case 1: separatorText="case 1"; break;
case 2: separatorText="case 2"; break;
//[...]
default: separatorText="[ERROR]"; break;
}
holder.separatorText.setText(separatorText);
} 
else {
//Set the name:
holder.name.setText(curValues.name);
//Set category
String cat = curValues.classification.toString();
cat = cat.substring(1,cat.length()-1);    //removing "[" and "]"
if (cat.length() > 35) {
cat = cat.substring(0, 35);
cat = cat + "...";
}
holder.category.setText(cat);
//[...] (and many more TextViews and ImageViews to be set)
}
listRow_previous = listRow;
Log.i(TAG,"Adapter: getView("+position+") -> DONE");
return convertView;
}
private class ViewHolder {
TextView name;
TextView category;
//[...] -> many more TextViews and ImageViews
TextView separatorText;
}
}

Et voici mon Logcat de sortie:

  755     ListPlaces_Activity  I  onPostExecute: notifyDataSetChanged()                                                                                                
755     ListPlaces_Activity  I  Adapter: getView(0) SEPARATOR (null) -> START                                                                                        
755     ListPlaces_Activity  I  --> (convertView == null) at position: 0                                                                                             
755     ListPlaces_Activity  I        CREATE SEPARATOR: convertView ID: 2131296317 Resource: android.content.res.Resources@437613e0                                  
755     ListPlaces_Activity  I  Adapter: getView(0) -> DONE                                                                                                          
755     ListPlaces_Activity  I  Adapter: getView(1) ITEM (SEPARATOR) -> START                                                                                        
755     ListPlaces_Activity  I  --> (convertView == null) at position: 1                                                                                             
755     ListPlaces_Activity  I        CREATE ITEM: convertView ID: 2131296317 Resource: android.content.res.Resources@437613e0                                       
755     ListPlaces_Activity  I  Adapter: getView(1) -> DONE                                                                                                          
755     ListPlaces_Activity  I  Adapter: getView(2) SEPARATOR (ITEM) -> START                                                                                        
755     ListPlaces_Activity  I  --> (convertView == null) at position: 2                                                                                             
755     ListPlaces_Activity  I        CREATE SEPARATOR: convertView ID: 2131296317 Resource: android.content.res.Resources@437613e0                                  
755     ListPlaces_Activity  I  Adapter: getView(2) -> DONE                                                                                                          
755     ListPlaces_Activity  I  Adapter: getView(3) ITEM (SEPARATOR) -> START                                                                                        
755     ListPlaces_Activity  I  --> (convertView == null) at position: 3                                                                                             
755     ListPlaces_Activity  I        CREATE ITEM: convertView ID: 2131296317 Resource: android.content.res.Resources@437613e0                                       
755     ListPlaces_Activity  I  Adapter: getView(3) -> DONE                                                                                                          
755     ListPlaces_Activity  I  Adapter: getView(4) ITEM (ITEM) -> START                                                                                             
755     ListPlaces_Activity  I        convertView ID: 2131296317 Resource: android.content.res.Resources@437613e0                                                    
755     ListPlaces_Activity  I  Adapter: getView(4) -> DONE                                                                                                          
755     ListPlaces_Activity  I  Adapter: getView(5) ITEM (ITEM) -> START                                                                                             
755     ListPlaces_Activity  I        convertView ID: 2131296317 Resource: android.content.res.Resources@437613e0                                                    
755     ListPlaces_Activity  I  Adapter: getView(5) -> DONE                                                                                                          
755     ListPlaces_Activity  I  Adapter: getView(6) ITEM (ITEM) -> START                                                                                             
755     ListPlaces_Activity  I        convertView ID: 2131296317 Resource: android.content.res.Resources@437613e0                                                    
755     ListPlaces_Activity  I  Adapter: getView(6) -> DONE                                                                                                          
755     ListPlaces_Activity  I  Adapter: getView(0) SEPARATOR (ITEM) -> START                                                                                        
755     ListPlaces_Activity  I  --> (convertView == null) at position: 0                                                                                             
755     ListPlaces_Activity  I        CREATE SEPARATOR: convertView ID: 2131296317 Resource: android.content.res.Resources@437613e0                                  
755     ListPlaces_Activity  I  Adapter: getView(0) -> DONE                                                                                                          
755     ListPlaces_Activity  I  Adapter: getView(1) ITEM (SEPARATOR) -> START                                                                                        
755     ListPlaces_Activity  I  --> (convertView == null) at position: 1                                                                                             
755     ListPlaces_Activity  I        CREATE ITEM: convertView ID: 2131296317 Resource: android.content.res.Resources@437613e0                                       
755     ListPlaces_Activity  I  Adapter: getView(1) -> DONE                                                                                                          
755     ListPlaces_Activity  I  Adapter: getView(2) SEPARATOR (ITEM) -> START                                                                                        
755     ListPlaces_Activity  I  --> (convertView == null) at position: 2                                                                                             
755     ListPlaces_Activity  I        CREATE SEPARATOR: convertView ID: 2131296317 Resource: android.content.res.Resources@437613e0                                  
755     ListPlaces_Activity  I  Adapter: getView(2) -> DONE                                                                                                          
755     ListPlaces_Activity  I  Adapter: getView(3) ITEM (SEPARATOR) -> START                                                                                        
755     ListPlaces_Activity  I  --> (convertView == null) at position: 3                                                                                             
755     ListPlaces_Activity  I        CREATE ITEM: convertView ID: 2131296317 Resource: android.content.res.Resources@437613e0                                       
755     ListPlaces_Activity  I  Adapter: getView(3) -> DONE                                                                                                          
755     ListPlaces_Activity  I  Adapter: getView(4) ITEM (ITEM) -> START                                                                                             
755     ListPlaces_Activity  I        convertView ID: 2131296317 Resource: android.content.res.Resources@437613e0                                                    
755     ListPlaces_Activity  I  Adapter: getView(4) -> DONE                                                                                                          
755     ListPlaces_Activity  I  Adapter: getView(5) ITEM (ITEM) -> START                                                                                             
755     ListPlaces_Activity  I        convertView ID: 2131296317 Resource: android.content.res.Resources@437613e0                                                    
755          AndroidRuntime  D  Shutting down VM                                                                                                                     
755                dalvikvm  W  threadid=3: thread exiting with uncaught exception (group=0x4001aa28)                                                                
755          AndroidRuntime  E  Uncaught handler: thread main exiting due to uncaught exception                                                                      
755          AndroidRuntime  E  java.lang.NullPointerException                                                                                                       
755          AndroidRuntime  E        at com.tato.main.ListPlaces_Activity$EfficientAdapter.getView(ListPlaces_Activity.java:330)                                    
755          AndroidRuntime  E        at android.widget.HeaderViewListAdapter.getView(HeaderViewListAdapter.java:191)                                                
755          AndroidRuntime  E        at android.widget.AbsListView.obtainView(AbsListView.java:1255)                                                                
755          AndroidRuntime  E        at android.widget.ListView.makeAndAddView(ListView.java:1658)                                                                  
755          AndroidRuntime  E        at android.widget.ListView.fillDown(ListView.java:637)                                                                         
755          AndroidRuntime  E        at android.widget.ListView.fillFromTop(ListView.java:694)                                                                      
755          AndroidRuntime  E        at android.widget.ListView.layoutChildren(ListView.java:1502)                                                                  
755          AndroidRuntime  E        at android.widget.AbsListView.onLayout(AbsListView.java:1112)                                                                  
755          AndroidRuntime  E        at android.view.View.layout(View.java:6569)                                                                                    
755          AndroidRuntime  E        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1119)                                                           
755          AndroidRuntime  E        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:998)                                                           
755          AndroidRuntime  E        at android.widget.LinearLayout.onLayout(LinearLayout.java:918)                                                                 
755          AndroidRuntime  E        at android.view.View.layout(View.java:6569)                                                                                    
755          AndroidRuntime  E        at android.widget.FrameLayout.onLayout(FrameLayout.java:333)                                                                   
755          AndroidRuntime  E        at android.view.View.layout(View.java:6569)                                                                                    
755          AndroidRuntime  E        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1119)                                                           
755          AndroidRuntime  E        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:998)                                                           
755          AndroidRuntime  E        at android.widget.LinearLayout.onLayout(LinearLayout.java:918)                                                                 
755          AndroidRuntime  E        at android.view.View.layout(View.java:6569)                                                                                    
755          AndroidRuntime  E        at android.widget.FrameLayout.onLayout(FrameLayout.java:333)                                                                   
755          AndroidRuntime  E        at android.view.View.layout(View.java:6569)                                                                                    
755          AndroidRuntime  E        at android.view.ViewRoot.performTraversals(ViewRoot.java:979)                                                                  
755          AndroidRuntime  E        at android.view.ViewRoot.handleMessage(ViewRoot.java:1613)                                                                     
755          AndroidRuntime  E        at android.os.Handler.dispatchMessage(Handler.java:99)                                                                         
755          AndroidRuntime  E        at android.os.Looper.loop(Looper.java:123)                                                                                     
755          AndroidRuntime  E        at android.app.ActivityThread.main(ActivityThread.java:4203)                                                                   
755          AndroidRuntime  E        at java.lang.reflect.Method.invokeNative(Native Method)                                                                        
755          AndroidRuntime  E        at java.lang.reflect.Method.invoke(Method.java:521)                                                                            
755          AndroidRuntime  E        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)                                             
755          AndroidRuntime  E        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:549)                                                                
755          AndroidRuntime  E        at dalvik.system.NativeStart.main(Native Method)    
Pourriez-vous ajouter un commentaire de montrer où la ligne de 300 est qui est dans la stacktrace? Si c'est if (curValues.separator >= 0), devriez-vous être capable de gérer les positions jusqu'à 1 au cours de la fin de la liste?

OriginalL'auteur znq | 2009-11-02