Las propuestas de optimización para ListView con datos de múltiples "tablas"

Acabo de encontrar la siguiente situación. Tengo una aplicación de Android con un escenario que supongo que puede suceder en varias aplicaciones. Se trata de etiquetado / etiquetado / categorización, llámalo como quieras. Básicamente tengo las siguientes relaciones en el SQLite DB

-------- -------------- --------- | Tags | | DeviceTags | | Devices | |--------| |--------------| |---------| | ID | 1 ------ * | ID | * ------ 1 | ID | | NAME | | TAGS_ID | | NAME | -------- | DEVICE_ID | | ... | -------------- --------- 

Todo está expuesto sobre un ContentProvider que he escrito. Hasta ahora todo está bien.

En la parte de interfaz de usuario, tengo una ListActivity que muestra todos los dispositivos almacenados (de la tabla Dispositivos) y para personalizar la interfaz de usuario un poco más, he creado elementos personalizados de fila mostrando una pequeña imagen en el frente basado en el tipo de dispositivo, etc.

Lo que me gustaría lograr ahora es mostrar también las etiquetas asociadas en esa lista para cada dispositivo. Ahora viene mi problema . Para la lista de dispositivos sencilla he creado un ResourceCursorAdapter personalizado donde establezco la información correspondiente en el método bindView

 @Override public void bindView(final View view, final Context context, final Cursor cursor) { final int objectId = cursor.getInt(cursor.getColumnIndex(Devices._ID)); TextView deviceName = (TextView) view.findViewById(R.id.deviceName); deviceName.setText(...); //set it from the cursor ... TextView associatedTagsView = (TextView)...; associatedTagsView.setText(...); //<<<???? This would need a call to a different table ... } 

Como puedes ver, por ser capaz de saber qué tipo de etiquetas de mi dispositivo se ha asociado, tendría que consultar DeviceTags. Así que lo hice:

 @Override public void bindView(final View view, final Context context, final Cursor cursor) { ... TextView associatedTagsView = (TextView)view.findViewById(R.id.deviceTags); String tagsString = retrieveTagsString(view.getContext().getContentResolver(), objectId); ... } private String retrieveTagsString(ContentResolver contentResolver, int objectId) { Cursor tagForDeviceCursor = contentResolver.query(DroidSenseProviderMetaData.TABLE_JOINS.TAG_DEVICETAG,...); if(tagForDeviceCursor != null && tagForDeviceCursor.moveToFirst()){ StringBuffer result = new StringBuffer(); boolean isFirst = true; do{ if(!isFirst) result.append(", "); else isFirst = false; result.append(retrieve name from cursor column...); }while(tagForDeviceCursor.moveToNext()); return result.toString(); } return null; } 

He probado esto y realmente funciona muy bien, pero para ser honesto, no me siento bien haciendo esto. De alguna manera me parece extraño …

¿Hay mejores soluciones sobre cómo resolver esto?

//Editar:

Después de los comentarios de CommonsWare aquí un poco de una aclaración. Soy extraño al hacer la segunda consulta al DB dentro del CursorAdapter, básicamente esto resultaría en una consulta por fila y me temo que esto impactará fuertemente mi rendimiento (todavía tengo que probarlo en un dispositivo real con una cantidad sustancial De datos para ver cuánto esto afecta).

Mi pregunta, por lo tanto, es si hay algunas estrategias sobre cómo evitar esto dado mi modelo de datos o si tengo que básicamente "vivir" con eso 🙂

Usted se quejó en Twitter que usted no estaba recibiendo ninguna retroalimentación. No estoy terriblemente sorprendido, porque mientras que su pregunta tiene un nivel de detalle ejemplar, sufre de dos defectos importantes:

  1. Su pregunta, al final, es vaga
  2. Su pregunta se basa en su propia interpretación de lo que "esto" es, al que no estamos al tanto

Por lo tanto, no tengo una imagen clara de lo que usted piensa que es "extraño". do...while() loops? Todos los derechos reservados

Voy a salir en una extremidad y supongo que su preocupación es hacer una segunda consulta y una ronda de concatenación de cadena para cada fila en su ListView . Todo depende de si piensa que "una lista de etiquetas delimitada por comas" es parte del modelo de datos o parte de la presentación. Si es parte de la presentación, no veo cómo puedes evitar lo que estás haciendo aquí.

Si realmente piensa que es parte de su modelo de datos, ajuste su ContentProvider para suministrar la lista de etiquetas delimitada por comas como parte de lo que esté consultando en primer lugar (no mostrado).

En cualquier caso, el rendimiento es un problema probable. Hacer una consulta por fila, particularmente en el momento de desplazamiento, es probable que sea malo. Después de todo, Romain Guy enfatiza repetidamente que necesita reciclar filas en su adaptador, y tendría que imaginar que una consulta de base de datos es un poco más cara que inflar un diseño. Desafortunadamente, usted fue con un modelo de datos que hizo hincapié en el espacio en el tiempo, y por lo que va a tener que pagar el piper en algún lugar a lo largo de la línea.

He probado mi solución (propuesta en mi pregunta) con alrededor de 100 entradas. Todavía era utilizable, pero el desplazamiento no era tan suave como cabría esperar. Como ya hemos señalado CommonsWare, lo mejor es adaptar el modelo de datos o al menos agregarlo correctamente st al final el cursor contiene todos los datos necesarios para ser mostrados en la interfaz de usuario .

No quería cambiar el datamodel subyacente por completo. Lo que hice es agregar los datos de una manera, st el cursor devuelto por el ContentProvider contiene los datos de los dispositivos, incluyendo una cadena ya preparada que representa los nombres de las etiquetas asociadas:

 | ID | NAME | ... | LABELSSTRING | ------------------------------------------------ | 1 | "My Device name" | ... | "Work, Friend" | | 1 | "Some other" | ... | | | 1 | "Yet another" | ... | "Work" | 

Esto soluciona bastante el problema, porque no hay necesidad de repetir en el bindView de CursorAdapter (..) para cada dispositivo, que btw. Es bastante malo. Esta solución fue posible mediante el uso de la función group_concat (X, Y) de SQLite.

  • ¿Debo confiar en Android para descartar los sorteos fuera de pantalla?
  • Cómo agregar palabras clave para optimizar la búsqueda de mi aplicación Android en google play store
  • ¿Es una optimización útil para los bucles en java?
  • ¿Problemas comunes de rendimiento en Android?
  • Cómo recortar un java stringbuilder?
  • ¿Por qué la API de Android solicita un parámetro de resultados en lugar de un método de devolución?
  • Optimización de un dibujo VBO enorme en dispositivos Android / iOS
  • ¿La manera más rápida de leer largo del archivo?
  • Optimización de la aplicación de Android antes del lanzamiento
  • OpenGL en Android versus iOS: optimizaciones, y donde difieren
  • APK no se instalará: DalvikVM no puede optimizarlo (el intercambio de bytes y la verificación fallan)
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.