2012-04-29 12 views
6

Por lo tanto, tengo un código que genera ID para una cantidad de elementos usando un AtomicInteger que está establecido por defecto en Integer.MAX_VALUE y se reduce a partir de ahí con cada ver que se le asigna una ID. Por lo tanto, la primera vista con una ID generada sería Integer.MAX_VALUE - 1, la segunda sería Integer.MAX_VALUE - 2, etc. El problema que me temo es una colisión con los ID generados por Android en R.java.Comprobando si existe una ID en los recursos (R.id.something)

Así que mi pregunta es cómo puedo detectar si un ID ya está en uso y omitirlo cuando estoy generando los ID. Solo estoy generando como máximo 30 identificaciones, por lo que esta no es una tuerca de gran prioridad, me gustaría hacer esto lo más libre posible de errores.

Respuesta

9

El siguiente código le dirá si el identificador es un identificador o no.

static final String PACKAGE_ID = "com.your.package.here:id/" 
... 
... 
int id = <your random id here> 
String name = getResources().getResourceName(id); 
if (name == null || !name.startsWith(PACKAGE_ID)) { 
    // id is not an id used by a layout element. 
} 
+0

¡Gracias! Esto parece prometedor. Ni siquiera pensé en usar getResources. Voy a tratar de salir. – Brandon

+0

@Brandon, debe actualizar su pregunta si tiene algo más que agregar. En cuanto a su edición, ¡será aún mejor como respuesta a su propia pregunta! – Ben

+4

'name' nunca será' null'. en cambio, '' Resources.NotFoundException' será lanzado por 'getResourceName()' si el identificador no es válido – sfera

0

Solo una idea ... podría usar el findViewById (int id) para comprobar si el id ya está en uso.

+2

que solo funcionaría si el contexto se estableció en la vista específica en la que se encuentra el ID. En otras palabras, con más de una vista y diferentes ID que nunca funcionarían como detección. – MikeIsrael

1

Puede usar Java Reflection API para acceder a los elementos que estén presentes en un objeto de clase R.id.

El código es así:

Class<R.id> c = R.id.class; 

R.id object = new R.id(); 

Field[] fields = c.getDeclaredFields(); 

// Iterate through whatever fields R.id has 
for (Field field : fields) 
{ 
    field.setAccessible(true); 

    // I am just printing field name and value, you can place your checks here 

    System.out.println("Value of " + field.getName() + " : " + field.get(object)); 
} 
+0

Parece que podría funcionar, pero decidí responder a @Jens – Brandon

3

he modificado respuesta Jens desde arriba, ya que, como se indica en los comentarios, nombre nunca será nula y sin excepción se produce en su lugar.

private boolean isResourceIdInPackage(String packageName, int resId){ 
    if(packageName == null || resId == 0){ 
     return false; 
    } 

    Resources res = null; 
    if(packageName.equals(getPackageName())){ 
     res = getResources(); 
    }else{ 
     try{ 
      res = getPackageManager().getResourcesForApplication(packageName); 
     }catch(PackageManager.NameNotFoundException e){ 
      Log.w(TAG, packageName + "does not contain " + resId + " ... " + e.getMessage()); 
     } 
    } 

    if(res == null){ 
     return false; 
    } 

    return isResourceIdInResources(res, resId); 
} 

private boolean isResourceIdInResources(Resources res, int resId){ 

    try{    
     getResources().getResourceName(resId); 

     //Didn't catch so id is in res 
     return true; 

    }catch (Resources.NotFoundException e){ 
     return false; 
    } 
} 
Cuestiones relacionadas