2012-04-29 73 views
6

所以,我目前正使用的是在默认情况下在Integer.MAX_VALUE的设置,并从那里递减与每个一个的AtomicInteger生成ID的许多元素的码获取分配ID的视图。因此,与生成的ID的第一个视图是Integer.MAX_VALUE - 1,第二是Integer.MAX_VALUE - 2等恐怕的问题是与在R.java由Android生成的ID的碰撞。检查,以查看是否在资源(R.id.something)存在的ID

所以我的问题是如何检测如果一个ID已经在使用并跳过它,当我生成的ID。我最多只能生成30个ID,所以这不是一个巨大的优先级,我希望尽可能使这个bug成为免费的。

回答

9

下面的代码会告诉你,如果标识符是一个ID或没有。

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

谢谢!这看起来有希望。我甚至没有想过使用getResources。我会尝试一下。 – Brandon 2012-04-29 16:59:35

+0

@Brandon,你应该更新你的问题,如果你有更多东西要添加。看看你的编辑,虽然它会更好地回答你自己的问题! – Ben 2012-04-29 19:26:06

+4

'name'永远不会是'null'。相反,如果标识符无效,则'getResourceName()'将抛出'Resources.NotFoundException' – sfera 2014-02-01 18:12:56

0

只是一个想法......你可以使用findViewById (int id)来检查id是否已被使用。

+2

这只有在上下文被设置为id所在的特定视图时才有效。换句话说,不止一个视图和不同的ID将不会用作检测。 – MikeIsrael 2012-04-29 09:01:14

1

可以使用Java Reflection API访问任何元素存在于R.id类的对象。

的代码是这样的:

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

这看起来像它可能工作,但我决定去@Jens回答 – Brandon 2012-04-29 18:48:37

3

我修改了Jens从上面回答,因为如评论中所述,name永远不会为空,而是抛出异常。

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; 
    } 
}