2010-11-21 6 views
1

J'ai un ListCursorAdapter personnalisé qui s'étend de SimpleCursorAdapter. Dans les lignes de la liste, il y a deux TextFields et un CheckBox. Lorsque vous faites défiler rapidement, le comportement des cases à cocher est bizarre; les "sélectionnés" sautent d'une rangée à l'autre, par ex. Si la troisième ligne contient une case à cocher sélectionnée et que je défile rapidement, une autre ligne est sélectionnée.Android: SimpleCursorAdapter.bindView fournit parfois null pour findViewById

je trouve que parfois, le findViewById dans mon Bindview méthode retourne null:

@Override 
public final View newView(final Context context, final Cursor cursor, final ViewGroup parent) { 
    final LayoutInflater inflater = LayoutInflater.from(context); 
    final View v = inflater.inflate(mLayout, null); 

    return v; 
} 

@Override 
public final void bindView(final View v, final Context context, final Cursor cursor) { 
    int haltestelleCol = cursor.getColumnIndex("haltestelle"); 
    int nameCol = cursor.getColumnIndex("name"); 
    int linieCol = cursor.getColumnIndex("linie"); 
    int startseiteCol = cursor.getColumnIndex("startseite"); 
    int idCol = cursor.getColumnIndex("_id"); 
    final String haltestelleString = cursor.getString(haltestelleCol); 
    final String nameString = cursor.getString(nameCol); 

    // Next set the haltestelle of the entry. 
    final TextView haltestelle = (TextView) v.findViewById(R.id.favorite_haltestelle); 
    if (haltestelle != null) { 
     if (nameString != null && !nameString.equals("")) { 
      haltestelle.setText(nameString); 
     } else { 
      haltestelle.setText(haltestelleString); 
     } 
    } 

    // next set the linie 
    final TextView linie = (TextView) v.findViewById(R.id.favorite_linie); 
    if (linie != null) { 
     linie.setText(cursor.getString(linieCol)); 
    } 

    // set startseite-flag or not 
    final int startseite = cursor.getInt(startseiteCol); 
    final CheckBox startseiteCheckbox = (CheckBox) v.findViewById(R.id.favorite_startseite); 
    final int id = cursor.getInt(idCol); 
    if (startseiteCheckbox != null) { 
     if (startseite > 0) { 
      startseiteCheckbox.setChecked(true); 
     } 

     checkboxes.add(startseiteCheckbox); 
     startseiteCheckbox.setId(id); 
     startseiteCheckbox.setOnClickListener(new StartseiteClickListener(cursor.getPosition())); 
    } else { 
     System.out.println(); 
    } 
} 

dire que je suis à la "System.out.println()" - partie. Quelqu'un peut-il me dire pourquoi j'ai ce comportement? Et est-ce correct que la méthode bindView est appelée souvent? Ne devrait-il pas être appelé seulement une fois par rangée?

Merci beaucoup!

Mise à jour: Il y a deux stacktraces différentes: Lorsque la case retour est non nulle (= quand il travaille), le StackTrace est la suivante:

Thread [<3> main] (Suspended (breakpoint at line 110 in FavoriteListCursorAdapter)) 
FavoriteListCursorAdapter.bindView(View, Context, Cursor) line: 110 
FavoriteListCursorAdapter(CursorAdapter).getView(int, View, ViewGroup) line: 186  
ListView(AbsListView).obtainView(int) line: 1274  
ListView.makeAndAddView(int, int, boolean, int, boolean) line: 1668 
ListView.fillUp(int, int) line: 667 
ListView.fillGap(boolean) line: 613 
ListView(AbsListView).trackMotionScroll(int, int) line: 2531  
ListView(AbsListView).onTouchEvent(MotionEvent) line: 2001 
ListView.onTouchEvent(MotionEvent) line: 3234 
ListView(View).dispatchTouchEvent(MotionEvent) line: 3709 
ListView(ViewGroup).dispatchTouchEvent(MotionEvent) line: 852 
LinearLayout(ViewGroup).dispatchTouchEvent(MotionEvent) line: 884 
ViewFlipper(ViewGroup).dispatchTouchEvent(MotionEvent) line: 884  
LinearLayout(ViewGroup).dispatchTouchEvent(MotionEvent) line: 884 
FrameLayout(ViewGroup).dispatchTouchEvent(MotionEvent) line: 884  
PhoneWindow$DecorView(ViewGroup).dispatchTouchEvent(MotionEvent) line: 884 
PhoneWindow$DecorView.superDispatchTouchEvent(MotionEvent) line: 1659 
PhoneWindow.superDispatchTouchEvent(MotionEvent) line: 1107 
FavoritenActivity(Activity).dispatchTouchEvent(MotionEvent) line: 2061 
PhoneWindow$DecorView.dispatchTouchEvent(MotionEvent) line: 1643  
FrameLayout(ViewGroup).dispatchTouchEvent(MotionEvent) line: 884  
LinearLayout(ViewGroup).dispatchTouchEvent(MotionEvent) line: 884 
TabHost(ViewGroup).dispatchTouchEvent(MotionEvent) line: 884  
FrameLayout(ViewGroup).dispatchTouchEvent(MotionEvent) line: 884  
LinearLayout(ViewGroup).dispatchTouchEvent(MotionEvent) line: 884 
PhoneWindow$DecorView(ViewGroup).dispatchTouchEvent(MotionEvent) line: 884 
PhoneWindow$DecorView.superDispatchTouchEvent(MotionEvent) line: 1659 
PhoneWindow.superDispatchTouchEvent(MotionEvent) line: 1107 
Scout(Activity).dispatchTouchEvent(MotionEvent) line: 2061 
PhoneWindow$DecorView.dispatchTouchEvent(MotionEvent) line: 1643  
ViewRoot.handleMessage(Message) line: 1691 
ViewRoot(Handler).dispatchMessage(Message) line: 99 
Looper.loop() line: 123 
ActivityThread.main(String[]) line: 4363  
Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method] 
Method.invoke(Object, Object...) line: 521 
ZygoteInit$MethodAndArgsCaller.run() line: 860 
ZygoteInit.main(String[]) line: 618 
NativeStart.main(String[]) line: not available [native method] 

Et quand l'objet retourné est nul, la StackTrace est le suivant:

Thread [<3> main] (Suspended (breakpoint at line 123 in FavoriteListCursorAdapter)) 
FavoriteListCursorAdapter.bindView(View, Context, Cursor) line: 123 
FavoriteListCursorAdapter(CursorAdapter).getView(int, View, ViewGroup) line: 186  
ListView(AbsListView).obtainView(int) line: 1256  
ListView.makeAndAddView(int, int, boolean, int, boolean) line: 1668 
ListView.fillUp(int, int) line: 667 
ListView.correctTooHigh(int) line: 1289 
ListView.fillGap(boolean) line: 609 
ListView(AbsListView).trackMotionScroll(int, int) line: 2531  
ListView(AbsListView).onTouchEvent(MotionEvent) line: 2001 
ListView.onTouchEvent(MotionEvent) line: 3234 
ListView(View).dispatchTouchEvent(MotionEvent) line: 3709 
ListView(ViewGroup).dispatchTouchEvent(MotionEvent) line: 852 
LinearLayout(ViewGroup).dispatchTouchEvent(MotionEvent) line: 884 
ViewFlipper(ViewGroup).dispatchTouchEvent(MotionEvent) line: 884  
LinearLayout(ViewGroup).dispatchTouchEvent(MotionEvent) line: 884 
FrameLayout(ViewGroup).dispatchTouchEvent(MotionEvent) line: 884  
PhoneWindow$DecorView(ViewGroup).dispatchTouchEvent(MotionEvent) line: 884 
PhoneWindow$DecorView.superDispatchTouchEvent(MotionEvent) line: 1659 
PhoneWindow.superDispatchTouchEvent(MotionEvent) line: 1107 
FavoritenActivity(Activity).dispatchTouchEvent(MotionEvent) line: 2061 
PhoneWindow$DecorView.dispatchTouchEvent(MotionEvent) line: 1643  
FrameLayout(ViewGroup).dispatchTouchEvent(MotionEvent) line: 884  
LinearLayout(ViewGroup).dispatchTouchEvent(MotionEvent) line: 884 
TabHost(ViewGroup).dispatchTouchEvent(MotionEvent) line: 884  
FrameLayout(ViewGroup).dispatchTouchEvent(MotionEvent) line: 884  
LinearLayout(ViewGroup).dispatchTouchEvent(MotionEvent) line: 884 
PhoneWindow$DecorView(ViewGroup).dispatchTouchEvent(MotionEvent) line: 884 
PhoneWindow$DecorView.superDispatchTouchEvent(MotionEvent) line: 1659 
PhoneWindow.superDispatchTouchEvent(MotionEvent) line: 1107 
Scout(Activity).dispatchTouchEvent(MotionEvent) line: 2061 
PhoneWindow$DecorView.dispatchTouchEvent(MotionEvent) line: 1643  
ViewRoot.handleMessage(Message) line: 1691 
ViewRoot(Handler).dispatchMessage(Message) line: 99 
Looper.loop() line: 123 
ActivityThread.main(String[]) line: 4363  
Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method] 
Method.invoke(Object, Object...) line: 521 
ZygoteInit$MethodAndArgsCaller.run() line: 860 
ZygoteInit.main(String[]) line: 618 
NativeStart.main(String[]) line: not available [native method] 
+1

oui, Bindview doit être appelé une fois par ligne, mais aussi quand vous faites défiler la liste. –

Répondre

0

vous pouvez remarquer un comportement bizarre - à savoir que vous verrez les noms commencer à changer lorsque vous faites défiler vers le haut et en bas de la liste. Ce qui se passe est que si vous n'instanciez pas et ne placez pas quelque chose dans votre TextView (essentiellement pour agir comme un espace réservé) alors dans votre méthode bindView rien ne sera lié à certains TextViews et donc au décalage. Donc, fondamentalement, si vous voyez des choses se déplacer dans vos listes, alors c'est un gros drapeau pour vous assurer que vous liez des choses à toutes vos vues dans vos méthodes newView et bindView.

Alors, pensez-instancier toutes vos vues si le texte/image définie dans la ligne du défilement list..else peut apparaître quelques erreurs ...