जवाबों:
View
प्रलेखन के अनुसार
इस दृश्य के पदानुक्रम में पहचानकर्ता का विशिष्ट होना आवश्यक नहीं है। पहचानकर्ता एक सकारात्मक संख्या होनी चाहिए।
इसलिए आप अपनी पसंद के किसी भी सकारात्मक पूर्णांक का उपयोग कर सकते हैं, लेकिन इस मामले में समतुल्य आईडी के साथ कुछ विचार हो सकते हैं। यदि आप पदानुक्रम में कुछ दृश्य देखने के लिए setTag
कुछ प्रमुख वस्तुओं के साथ कॉल करना चाहते हैं तो यह आसान हो सकता है।
findViewById
पहले इसे वापस मिलेगा।
setContentView()
लें कि उनके आइडी के साथ 10 आइडिया एक ही पदानुक्रम में एक ही आईडी नंबर पर सेट है , तो कॉल findViewById([repeated_id])
एक बार दोहराया जाने वाले आईडी के साथ सेट किए गए पहले दृश्य को वापस करेगा। मेरा मतलब यही था।
एपीआई स्तर 17 और ऊपर से, आप कॉल कर सकते हैं: View.generateViewId ()
इसके बाद View.setId (int) का उपयोग करें ।
यदि आपका ऐप API स्तर 17 से कम लक्षित है, तो ViewCompat.generateViewId () का उपयोग करें
AtomicInteger
तरीकों के कार्यान्वयन पर एक नज़र है ।
for(;;)
मैंने जो देखा है वह पहले कभी नहीं देखा। किसे कहते है?
आप R.id
एक xml संसाधन फ़ाइल का उपयोग करते हुए कक्षा में बाद में आईडी का उपयोग कर सकते हैं, और संकलन समय के दौरान एंड्रॉइड एसडीके उन्हें अद्वितीय मान दे सकते हैं।
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++
का उपयोग करता है, एक अद्वितीय आईडी सुनिश्चित करता है, और मैं स्टोर कर सकता हूं मेरे ArrayList में बाद में उपयोग के लिए आईडी।
<resources>
।
इसके अलावा, आप को परिभाषित कर सकते ids.xml
में res/values
। आप Android के नमूना कोड में एक सटीक उदाहरण देख सकते हैं।
samples/ApiDemos/src/com/example/android/apis/RadioGroup1.java
samples/ApiDemp/res/values/ids.xml
एपीआई 17 के बाद से, View
क्लास में एक स्थिर तरीका है generateViewId()
जो होगा
setId (int) में उपयोग के लिए उपयुक्त मान उत्पन्न करना
यह मेरे लिए काम करता है:
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 के जवाब के लिए एक टिप्पणी थी लेकिन यह बहुत लंबा हो गया ... hehe)
बेशक एक स्थिर यहाँ की जरूरत नहीं है। आप स्थैतिक के बजाय, सहेजने के लिए SharedPreferences का उपयोग कर सकते हैं। किसी भी तरह से, कारण वर्तमान प्रगति को बचाने के लिए है ताकि इसकी जटिल लेआउट के लिए बहुत धीमा न हो। क्योंकि, वास्तव में, एक बार उपयोग करने के बाद, यह बाद में तेजी से होगा। हालांकि, मुझे नहीं लगता कि यह ऐसा करने का एक अच्छा तरीका है क्योंकि अगर आपको अपनी स्क्रीन को फिर से बनाना है (जैसा कि फिर से कहा onCreate
जाता है), तो आप शायद किसी भी तरह से शुरुआत करना चाहते हैं, स्थैतिक की आवश्यकता को समाप्त करना। इसलिए, स्थैतिक के बजाय इसे केवल एक उदाहरण चर बनाएं।
यहां एक छोटा संस्करण है जो थोड़ा तेज चलता है और पढ़ने में आसान हो सकता है:
int fID = 0;
public int findUnusedId() {
while( findViewById(++fID) != null );
return fID;
}
यह उपरोक्त कार्य पर्याप्त होना चाहिए। क्योंकि, जहां तक मैं बता सकता हूं, एंड्रॉइड-जनरेटेड आईडी अरबों में हैं, इसलिए यह संभवत: 1
पहली बार वापस आएगा और हमेशा काफी तेज होगा। क्योंकि, यह वास्तव में एक अप्रयुक्त को खोजने के लिए इस्तेमाल की गई आईडी के पिछले पाशन होना चाहिए। हालाँकि, लूप है कि यह वास्तव में एक इस्तेमाल किया आईडी मिलनी चाहिए।
हालाँकि, यदि आप अभी भी अपने ऐप के बाद के मनोरंजन के बीच प्रगति को सहेजना चाहते हैं, और स्थैतिक का उपयोग करने से बचना चाहते हैं। यहाँ साझाकरण संस्करण है:
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;
}
इसी तरह के एक सवाल का जवाब आपको वह सब कुछ बता देना चाहिए जो आपको आईडी के बारे में जानना चाहिए: https://stackoverflow.com/a/13241629/693927
EDIT / FIX: बस एहसास हुआ कि मैं पूरी तरह से बचाने के लिए goofed। मैं नशे में धुत हो गया होगा।
'कम्पैटिबल' लाइब्रेरी अब generateViewId()
एपीआई लेवल से पहले 17 के लिए विधि का भी समर्थन करती है ।
बस Compat
पुस्तकालय के एक संस्करण का उपयोग करना सुनिश्चित करें जो है27.1.0+
उदाहरण के लिए, आपकी build.gradle
फ़ाइल में:
implementation 'com.android.support:appcompat-v7:27.1.1
फिर आप केवल कक्षा के बजाय कक्षा generateViewId()
से निम्नानुसार उपयोग कर सकते हैं :ViewCompat
View
//Will assign a unique ID
myView.id = ViewCompat.generateViewId()
हैप्पी कोडिंग!
@ हाथीकोमबेल के उत्तर के लिए एक अतिरिक्त,
जबकि View.generateViewId()
API स्तर की आवश्यकता है> = 17,
यह उपकरण सभी एपीआई के साथ कंपैटिबल है।
वर्तमान एपीआई स्तर के अनुसार,
यह सिस्टम एपीआई या नहीं का उपयोग करके मौसम तय करता है।
इसलिए आप एक ही समय में उपयोग कर सकते हैं ViewIdGenerator.generateViewId()
और View.generateViewId()
एक ही आईडी प्राप्त करने के बारे में चिंता न करें
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 उपकरणों की तुलना में छोटे एपीआई स्तर के लिए अनंत लूप में जाएगा?
आदेश में गतिशील रूप से देखें आईडी फॉर्म एपीआई 17 का उपयोग करें
जो कि उपयोग के लिए उपयुक्त मूल्य उत्पन्न करेगा setId(int)
। यह मान aapt द्वारा निर्मित समय पर बनाए गए ID मानों से नहीं टकराएगा R.id
।
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 synchronized int generateViewId() {
Random rand = new Random();
int id;
while (findViewById(id = rand.nextInt(Integer.MAX_VALUE) + 1) != null);
return id;
}
एक यादृच्छिक संख्या का उपयोग करके मुझे हमेशा पहले प्रयास में अद्वितीय आईडी प्राप्त करने का एक बड़ा मौका मिलता है।
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
कोई गारंटी देता है कि अगर एक ही आईडी के साथ एक से अधिक है तो किस दृश्य को लौटाया जाए? डॉक्स कुछ भी उल्लेख नहीं करता है।