2012-04-29 108 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; 
    } 
}