Acabo de encontrar la siguiente situación. Tengo una aplicación para Android con un escenario que supongo que puede suceder en varias aplicaciones. Se trata de etiquetar/etiquetar/categorizar, llámalo como quieras. Básicamente tengo las siguientes relaciones en la DB SQLitePropuestas de optimización para ListView con datos de varias "tablas"
-------- -------------- ---------
| Tags | | DeviceTags | | Devices |
|--------| |--------------| |---------|
| ID | 1 ------ * | ID | * ------ 1 | ID |
| NAME | | TAGS_ID | | NAME |
-------- | DEVICE_ID | | ... |
-------------- ---------
Todo está expuesto en un ContentProvider que he escrito. Hasta ahora todo está bien.
En la parte de IU, tengo una actividad de lista que muestra todos los dispositivos almacenados (de la tabla Dispositivos) y para personalizar un poco más la IU, creé elementos de fila personalizados mostrando una imagen pequeña en el frente según 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 aquí viene mi problema. Para la lista de dispositivos simples creé una ResourceCursorAdapter personalizada donde hice la información de acuerdo 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 se puede ver, por ser capaz de saber qué tipo de etiquetas de mi dispositivo ha asociado, necesitaría para 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 que en realidad funciona bien, pero para ser honesto, no me siento bien haciendo esto. De alguna manera me parece extraño ...
¿Hay alguna solución mejor sobre cómo solucionar esto?
// Edición:
Tras los comentarios de CommonsWare aquí un poco de una aclaración. Soy extraño acerca de hacer la segunda consulta al DB dentro del CursorAdapter, básicamente esto daría lugar a una consulta por fila y me temo que esto tendrá un gran impacto en mi rendimiento (aún tengo que probarlo en un dispositivo real con una cantidad sustancial de datos para ver cuánto afecta esto).
Mi pregunta es, por tanto, de si hay algunas estrategias sobre cómo evitar esto dado mi modelo de datos o si tengo que básicamente "en vivo" con eso :)
Lo siento por mi pregunta algo vaga. No lo noté y lo arreglé ahora. Pero coincidió perfectamente con mis problemas (+1 por eso) :) El rendimiento es exactamente lo que necesita. Pero dado el requisito de que 1 dispositivo tenga múltiples etiquetas, tendré que ir con el diseño de DB que se muestra arriba ... Por supuesto, lo que podría hacer es "fusionar" DeviceTags y Tags de alguna manera, pero supongo que esto sería bastante feo. ... Tal vez sería mejor unirme a todo en el nivel de elemento de ContentProvider Ya tengo los datos listos ... Lo intentaré si veo que la solución actual tiene un gran impacto en el rendimiento. – Juri
También trataría de evitar la segunda consulta en el adaptador. Simplemente cree su proveedor de contenidos de forma que todos los datos necesarios en la lista estén presentes en el momento en que se muestran al usuario. – Janusz
@Juri: "Pero dado el requisito de que 1 dispositivo tenga varias etiquetas, tendré que ir con el diseño de base de datos que se muestra arriba" - no, no es así. Solo necesita eso si también va a los datos del lado de la etiqueta, y con la frecuencia suficiente para que valga la pena. Su alternativa es desnormalizar los datos, teniendo la lista de etiquetas delimitada por comas como una sola columna en la tabla del dispositivo. – CommonsWare