Answers:
根据View
文件
标识符在此视图的层次结构中不必唯一。标识符应为正数。
因此,您可以使用任何喜欢的正整数,但是在这种情况下,可能会有一些具有相同ID的视图。如果要在层次结构中搜索某些视图,则可以setTag
使用一些关键对象进行调用。
findViewById
则将返回它找到的第一个视图。
setContentView()
有10个视图,其ID设置为同一层次结构中的相同ID号,则调用findViewById([repeated_id])
将返回具有该重复ID的第一个视图集。我正是这个意思。
从API级别17及更高级别,您可以调用:View.generateViewId()
然后使用View.setId(int)。
如果您的应用的定位低于API级别17,请使用ViewCompat.generateViewId()
AtomicInteger
方法的实现。
for(;;)
我以前从未见过什么。那叫什么
您可以设置ID,以便稍后在R.id
课堂上使用xml资源文件使用,并让Android SDK在编译时为它们提供唯一值。
res/values/ids.xml
<item name="my_edit_text_1" type="id"/>
<item name="my_button_1" type="id"/>
<item name="my_time_picker_1" type="id"/>
要在代码中使用它:
myEditTextView.setId(R.id.my_edit_text_1);
"int currentId = 1000; whateverView.setId(currentId++);
-每次currentId++
使用时都会增加ID ,从而确保唯一ID,并且我可以存储我的ArrayList中的ID,以供以后访问。
<resources>
。
您也可以ids.xml
在中定义res/values
。您可以在android的示例代码中看到确切的示例。
samples/ApiDemos/src/com/example/android/apis/RadioGroup1.java
samples/ApiDemp/res/values/ids.xml
这对我有用:
static int id = 1;
// Returns a valid id that isn't in use
public int findId(){
View v = findViewById(id);
while (v != null){
v = findViewById(++id);
}
return id++;
}
findViewById()
操作缓慢。该方法有效,但以性能为代价。
(这是对dilettante的回答的评论,但时间太长了……呵呵)
当然,这里不需要静态的。您可以使用SharedPreferences进行保存,而不是使用静态方法。无论哪种方式,其原因都是要保存当前的进度,以使它对于复杂的布局不会太慢。因为,实际上,它一旦使用一次,以后就会很快。但是,我不认为这是个好方法,因为如果您必须再次重建屏幕(例如onCreate
再次调用),那么您可能无论如何都要从头开始,从而消除了对静态的需求。因此,只需使其成为实例变量而不是静态变量即可。
这是一个较小的版本,运行速度更快,并且可能更易于阅读:
int fID = 0;
public int findUnusedId() {
while( findViewById(++fID) != null );
return fID;
}
上述功能应该足够了。因为据我所知,android生成的ID数以十亿计,因此这很可能会1
第一次返回,并且总是非常快。因为,它实际上不会循环经过使用的ID来找到未使用的ID。但是,循环是如果实际找到了一个已使用的ID存在。
但是,如果您仍然希望在以后的应用程序重新创建之间保存进度,并希望避免使用静态方法。这是SharedPreferences版本:
SharedPreferences sp = getSharedPreferences("your_pref_name", MODE_PRIVATE);
public int findUnusedId() {
int fID = sp.getInt("find_unused_id", 0);
while( findViewById(++fID) != null );
SharedPreferences.Editor spe = sp.edit();
spe.putInt("find_unused_id", fID);
spe.commit();
return fID;
}
这个类似问题的答案应该告诉您有关android ID的所有信息: https //stackoverflow.com/a/13241629/693927
编辑/修正:刚意识到我完全搞砸了保存。我一定喝醉了。
除了@phantomlimb的答案之外,
而View.generateViewId()
要求API级别> = 17,
此工具与所有API兼容。
根据当前的API级别,
它是否使用系统API来确定天气。
这样您就可以同时使用ViewIdGenerator.generateViewId()
和View.generateViewId()
,而不必担心获得相同的ID
import java.util.concurrent.atomic.AtomicInteger;
import android.annotation.SuppressLint;
import android.os.Build;
import android.view.View;
/**
* {@link View#generateViewId()}要求API Level >= 17,而本工具类可兼容所有API Level
* <p>
* 自动判断当前API Level,并优先调用{@link View#generateViewId()},即使本工具类与{@link View#generateViewId()}
* 混用,也能保证生成的Id唯一
* <p>
* =============
* <p>
* while {@link View#generateViewId()} require API Level >= 17, this tool is compatibe with all API.
* <p>
* according to current API Level, it decide weather using system API or not.<br>
* so you can use {@link ViewIdGenerator#generateViewId()} and {@link View#generateViewId()} in the
* same time and don't worry about getting same id
*
* @author fantouchx@gmail.com
*/
public class ViewIdGenerator {
private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
@SuppressLint("NewApi")
public static int generateViewId() {
if (Build.VERSION.SDK_INT < 17) {
for (;;) {
final int result = sNextGeneratedId.get();
// aapt-generated IDs have the high byte nonzero; clamp to the range under that.
int newValue = result + 1;
if (newValue > 0x00FFFFFF)
newValue = 1; // Roll over to 1, not 0.
if (sNextGeneratedId.compareAndSet(result, newValue)) {
return result;
}
}
} else {
return View.generateViewId();
}
}
}
for (;;) { … }
来自Android源代码。
generateViewId()
else { return View.generateViewId(); }
对于小于17个设备的api级别,这将进入无限循环?
int fID;
do {
fID = Tools.generateViewId();
} while (findViewById(fID) != null);
view.setId(fID);
...
public class Tools {
private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
public static int generateViewId() {
if (Build.VERSION.SDK_INT < 17) {
for (;;) {
final int result = sNextGeneratedId.get();
int newValue = result + 1;
if (newValue > 0x00FFFFFF)
newValue = 1; // Roll over to 1, not 0.
if (sNextGeneratedId.compareAndSet(result, newValue)) {
return result;
}
}
} else {
return View.generateViewId();
}
}
}
public String TAG() {
return this.getClass().getSimpleName();
}
private AtomicInteger lastFldId = null;
public int generateViewId(){
if(lastFldId == null) {
int maxFld = 0;
String fldName = "";
Field[] flds = R.id.class.getDeclaredFields();
R.id inst = new R.id();
for (int i = 0; i < flds.length; i++) {
Field fld = flds[i];
try {
int value = fld.getInt(inst);
if (value > maxFld) {
maxFld = value;
fldName = fld.getName();
}
} catch (IllegalAccessException e) {
Log.e(TAG(), "error getting value for \'"+ fld.getName() + "\' " + e.toString());
}
}
Log.d(TAG(), "maxId="+maxFld +" name="+fldName);
lastFldId = new AtomicInteger(maxFld);
}
return lastFldId.addAndGet(1);
}
findViewById
如果有多个具有相同ID的视图返回,那么是否可以保证返回哪个视图呢?该文档没有提及任何内容。