2012-04-25 18 views
5

Tengo un listView con un adaptador personalizado. Cuando sucede algo (un clic en un niño) hago algunos cálculos y modifico la vista infantil. SI se ha cumplido alguna condición, se debe modificar otro hijo que no esté relacionado con el elemento secundario al que se hizo clic.A veces listView.getChildAt (índice int) devuelve NULL (Android)

Esto funciona a veces, pero a veces falla y las DDM dice que la vista es nula ...

Te voy a enseñar el código:

 if(invalidaEste != -1) 
     { 
      try 
      { 
       View v = lv_data.getChildAt(invalidaEste); 
       if(v== null) 
       { 
        Log.e("MY_LOG", "SIZE " + lv_data.getCount()); 
        Log.e("MY_LOG", "IS_NULL " + String.valueOf(invalidaEste)); 
       } 

       if(invalidaEste >= lv_data.getFirstVisiblePosition() && 
        invalidaEste <= lv_data.getLastVisiblePosition()) 
       { 
        RelacionFacturaPago rpf = (RelacionFacturaPago)lv_data.getAdapter().getItem(invalidaEste); 
        TextView tv = (TextView)v.findViewById(R.id.tv_pendiente); 
        tv.setText(Formato.double2Screen(rpf.getPorPagar())); 
       } 
      } 
      catch (Exception e) 
      { 
       Log.e("MY_LOG", "FAIL"); 
       Log.e("MY_LOG", String.valueOf(invalidaEste)); 
      } 

     } 

invalidaEste es la vista que yo quiero Modificar. Cuando v es nulo Registre el índice para comprobar si está correcto. Siempre es más pequeño o igual que listView.getCount()

¿Por qué ocurre esto?

Más datos: El código está dentro de onAnimationStart (animación de animación) de un oyente de AnimationListener.

+0

¿el adaptador tiene valores 'nulos'? – zapl

+0

posible duplicado de [ListView getChildAt devolver nulo para hijos visibles] (http://stackoverflow.com/questions/6766625/listview-getchildat-returning-null-for-visible-children) – rds

Respuesta

9

Debido al reciclaje de vista, listView.getChildAt() solo devolverá una vista para las posiciones que se muestran, y tal vez una más. Tal vez si comparte más de su código, podemos ayudarlo a encontrar la mejor manera de abordar el problema.

+0

La vista nula es una vista visible. – Desenfoque

+1

mmm ... Creo que veo tu punto ... El problema se desencadena cuando la vista con el índice 0 no está visible ... No entiendo bien el método getChildAt() ... – Desenfoque

+0

¿Esto está realmente roto? Veo que ya eres este control: 'if (invalidaEste> = lv_data.getFirstVisiblePosition() && invalidaEste <= lv_data.getLastVisiblePosition())', y cualquier otra vista debe ser actualizada por el adaptador cuando la desplazas hacia la vista . – dmon

1

Si ese niño no está visible en la pantalla, significa que no hay una vista para él. Creo que este es tu caso no funcional.

Una buena práctica es cambiar los datos detrás de su adaptador de lista y llamar a notifyDataSetChanged() en el adaptador. Esto informará la lista del adaptador que ha cambiado y volverá a pintar las vistas.

Si realmente desea actualizar manualmente la vista, supongo que la única solución es retener los nuevos valores en algún lugar y esperar hasta que la vista se vuelva visible. En ese momento, tiene una referencia válida y puede hacer las actualizaciones.

+0

Gracias por su respuesta .... Como puede ver en el código, utilizo la vista (v) solo cuando el índice pertenece a un elemento visible. No estoy utilizando notifyDataSetChanged() porque cancela las animaciones en ListView. – Desenfoque

+0

Veo que obtiene el hijo cuando invalidaEste! = -1. Esto no significa que sea un índice con vista visible, sino un índice que podría ser bueno. ¿Hay algún código además de lo que quería pegar y no está visible? – azertiti

+0

invalidaEste! = -1 solo dime que es un índice válido. Yo uso if (invalidaEste> = lv_data.getFirstVisiblePosition() && invalidaEste <= lv_data.getLastVisiblePosition()) para verificar si está visible. – Desenfoque

4

Dmon y Azertiti son correctos ... una vez que se desplaza su lista se encuentra en problemas. Si la vista no está visible, entonces no existe (es decir, ha sido reciclada por Android). Vas a volver a construir la vista una vez que se desplaza en

Hacer algo como esto debería funcionar:.

View view; 

int nFirstPos = lv_data.getFirstVisiblePosition(); 
int nWantedPos = invalidaEste - nFirstPos; 

if ((nWantedPos >= 0) && (nWantedPos <= lv_data.getChildCount()) 
{ 
view = lv_data.getChildAt(nWantedPos); 
if (view == null) 
    return; 
// else we have the view we want 
} 
1

lo prueba con una línea de código cuando tengo que ir dentro de una posición válida de una Vista de la lista. aquí están sus variables usadas como un ejemplo. donde lv_data es ListView y tv es su TextView.

if (lv_data.getChildAt(lv_data.getPositionForView(tv)) != null) { 
    int position = lv_data.getPositionForView(tv); 
} 
Cuestiones relacionadas